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.

1437 lines
31 KiB

  1. /*++
  2. Copyright (c) 1994-2001 Microsoft Corporation
  3. Module Name :
  4. iismbnode.cpp
  5. Abstract:
  6. CIISMBNode Object
  7. Author:
  8. Ronald Meijer (ronaldm)
  9. Sergei Antonov (sergeia)
  10. Project:
  11. Internet Services Manager
  12. Revision History:
  13. 10/28/2000 sergeia Split from iisobj.cpp
  14. --*/
  15. #include "stdafx.h"
  16. #include "common.h"
  17. #include "inetprop.h"
  18. #include "InetMgrApp.h"
  19. #include "supdlgs.h"
  20. #include "iisobj.h"
  21. #include "ftpsht.h"
  22. #include "w3sht.h"
  23. #include "fltdlg.h"
  24. #include "pwiz.h"
  25. #include <lm.h>
  26. #ifdef _DEBUG
  27. #undef THIS_FILE
  28. static char BASED_CODE THIS_FILE[] = __FILE__;
  29. #endif
  30. #define new DEBUG_NEW
  31. //
  32. // CIISMBNode implementation
  33. //
  34. // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  35. /* static */ LPOLESTR CIISMBNode::_cszSeparator = _T("/");
  36. CIISMBNode::CIISMBNode(
  37. IN CIISMachine * pOwner,
  38. IN LPCTSTR szNode
  39. )
  40. /*++
  41. Routine Description:
  42. Constructor
  43. Arguments:
  44. CIISMachine * pOwner : Owner machine object
  45. LPCTSTR szNode : Node name
  46. Return Value:
  47. N/A
  48. --*/
  49. : m_bstrNode(szNode),
  50. m_bstrURL(NULL),
  51. m_pOwner(pOwner)
  52. {
  53. ASSERT_READ_PTR(szNode);
  54. ASSERT_READ_PTR(pOwner);
  55. }
  56. CIISMBNode::~CIISMBNode()
  57. {
  58. RemoveResultItems();
  59. }
  60. void
  61. CIISMBNode::SetErrorOverrides(
  62. IN OUT CError & err,
  63. IN BOOL fShort
  64. ) const
  65. /*++
  66. Routine Description:
  67. Set error message overrides
  68. Arguments:
  69. CError err : Error message object
  70. BOOL fShort : TRUE to use only single-line errors
  71. Return Value:
  72. None
  73. --*/
  74. {
  75. //
  76. // Substitute friendly message for some ID codes.
  77. //
  78. // CODEWORK: Add global overrides as well.
  79. //
  80. err.AddOverride(EPT_S_NOT_REGISTERED,
  81. fShort ? IDS_ERR_RPC_NA_SHORT : IDS_ERR_RPC_NA);
  82. err.AddOverride(RPC_S_SERVER_UNAVAILABLE,
  83. fShort ? IDS_ERR_RPC_NA_SHORT : IDS_ERR_RPC_NA);
  84. err.AddOverride(RPC_S_UNKNOWN_IF, IDS_ERR_INTERFACE);
  85. err.AddOverride(RPC_S_PROCNUM_OUT_OF_RANGE, IDS_ERR_INTERFACE);
  86. err.AddOverride(REGDB_E_CLASSNOTREG, IDS_ERR_NO_INTERFACE);
  87. if (!fShort)
  88. {
  89. err.AddOverride(ERROR_ACCESS_DENIED, IDS_ERR_ACCESS_DENIED);
  90. }
  91. }
  92. BOOL
  93. CIISMBNode::IsAdministrator() const
  94. {
  95. CIISMBNode * that = (CIISMBNode *)this;
  96. return that->GetOwner()->HasAdministratorAccess();
  97. }
  98. void
  99. CIISMBNode::DisplayError(
  100. IN OUT CError & err
  101. ) const
  102. /*++
  103. Routine Description:
  104. Display error message box. Substituting some friendly messages for
  105. some specific error codes
  106. Arguments:
  107. CError & err : Error object contains code to be displayed
  108. Return Value:
  109. Noen
  110. --*/
  111. {
  112. SetErrorOverrides(err);
  113. err.MessageBox();
  114. }
  115. CIISMBNode *
  116. CIISMBNode::GetParentNode() const
  117. /*++
  118. Routine Description:
  119. Helper function to return the parent node in the scope tree
  120. Arguments:
  121. None
  122. Return Value:
  123. Parent CIISMBNode or NULL.
  124. --*/
  125. {
  126. LONG_PTR cookie = NULL;
  127. HSCOPEITEM hParent;
  128. CIISMBNode * pNode = NULL;
  129. HRESULT hr = S_OK;
  130. ASSERT_PTR(_lpConsoleNameSpace);
  131. if (m_hResultItem != 0)
  132. {
  133. SCOPEDATAITEM si;
  134. ::ZeroMemory(&si, sizeof(SCOPEDATAITEM));
  135. si.mask = SDI_PARAM;
  136. si.ID = m_hScopeItem;
  137. hr = _lpConsoleNameSpace->GetItem(&si);
  138. if (SUCCEEDED(hr))
  139. {
  140. cookie = si.lParam;
  141. }
  142. }
  143. else
  144. {
  145. hr = _lpConsoleNameSpace->GetParentItem(
  146. m_hScopeItem,
  147. &hParent,
  148. &cookie
  149. );
  150. }
  151. if (SUCCEEDED(hr))
  152. {
  153. pNode = (CIISMBNode *)cookie;
  154. ASSERT_PTR(pNode);
  155. }
  156. return pNode;
  157. }
  158. /* virtual */
  159. HRESULT
  160. CIISMBNode::BuildMetaPath(
  161. OUT CComBSTR & bstrPath
  162. ) const
  163. /*++
  164. Routine Description:
  165. Recursively build up the metabase path from the current node
  166. and its parents
  167. Arguments:
  168. CComBSTR & bstrPath : Returns metabase path
  169. Return Value:
  170. HRESULT
  171. --*/
  172. {
  173. HRESULT hr = S_OK;
  174. CIISMBNode * pNode = GetParentNode();
  175. if (pNode)
  176. {
  177. hr = pNode->BuildMetaPath(bstrPath);
  178. if (SUCCEEDED(hr))
  179. {
  180. bstrPath.Append(_cszSeparator);
  181. bstrPath.Append(QueryNodeName());
  182. }
  183. return hr;
  184. }
  185. //
  186. // No parent node
  187. //
  188. ASSERT_MSG("No parent node");
  189. return E_UNEXPECTED;
  190. }
  191. HRESULT
  192. CIISMBNode::FillCustomData(CLIPFORMAT cf, LPSTREAM pStream)
  193. {
  194. HRESULT hr = DV_E_CLIPFORMAT;
  195. ULONG uWritten;
  196. if (cf == m_CCF_MachineName)
  197. {
  198. hr = pStream->Write(
  199. QueryMachineName(),
  200. (ocslen((OLECHAR*)QueryMachineName()) + 1) * sizeof(OLECHAR),
  201. &uWritten
  202. );
  203. ASSERT(SUCCEEDED(hr));
  204. return hr;
  205. }
  206. //
  207. // Generate complete metabase path for this node
  208. //
  209. CString strField;
  210. CString strMetaPath;
  211. CComBSTR bstr;
  212. if (FAILED(hr = BuildMetaPath(bstr)))
  213. {
  214. ASSERT(FALSE);
  215. return hr;
  216. }
  217. strMetaPath = bstr;
  218. if (cf == m_CCF_MetaPath)
  219. {
  220. //
  221. // Whole metabase path requested
  222. //
  223. strField = strMetaPath;
  224. }
  225. else
  226. {
  227. //
  228. // A portion of the metabase is requested. Return the requested
  229. // portion
  230. //
  231. LPCTSTR lpMetaPath = (LPCTSTR)strMetaPath;
  232. LPCTSTR lpEndPath = lpMetaPath + strMetaPath.GetLength() + 1;
  233. LPCTSTR lpSvc = NULL;
  234. LPCTSTR lpInstance = NULL;
  235. LPCTSTR lpParent = NULL;
  236. LPCTSTR lpNode = NULL;
  237. //
  238. // Break up the metabase path in portions
  239. //
  240. if (lpSvc = _tcschr(lpMetaPath, _T('/')))
  241. {
  242. ++lpSvc;
  243. if (lpInstance = _tcschr(lpSvc, _T('/')))
  244. {
  245. ++lpInstance;
  246. if (lpParent = _tcschr(lpInstance, _T('/')))
  247. {
  248. ++lpParent;
  249. lpNode = _tcsrchr(lpParent, _T('/'));
  250. if (lpNode)
  251. {
  252. ++lpNode;
  253. }
  254. }
  255. }
  256. }
  257. int n1, n2;
  258. if (cf == m_CCF_Service)
  259. {
  260. //
  261. // Requested the service string
  262. //
  263. if (lpSvc)
  264. {
  265. n1 = DIFF(lpSvc - lpMetaPath);
  266. n2 = lpInstance ? DIFF(lpInstance - lpSvc) : DIFF(lpEndPath - lpSvc);
  267. strField = strMetaPath.Mid(n1, n2 - 1);
  268. }
  269. }
  270. else if (cf == m_CCF_Instance)
  271. {
  272. //
  273. // Requested the instance number
  274. //
  275. if (lpInstance)
  276. {
  277. n1 = DIFF(lpInstance - lpMetaPath);
  278. n2 = lpParent ? DIFF(lpParent - lpInstance) : DIFF(lpEndPath - lpInstance);
  279. strField = strMetaPath.Mid(n1, n2 - 1);
  280. }
  281. }
  282. else if (cf == m_CCF_ParentPath)
  283. {
  284. //
  285. // Requestd the parent path
  286. //
  287. if (lpParent)
  288. {
  289. n1 = DIFF(lpParent - lpMetaPath);
  290. n2 = lpNode ? DIFF(lpNode - lpParent) : DIFF(lpEndPath - lpParent);
  291. strField = strMetaPath.Mid(n1, n2 - 1);
  292. }
  293. }
  294. else if (cf == m_CCF_Node)
  295. {
  296. //
  297. // Requested the node name
  298. //
  299. if (lpNode)
  300. {
  301. n1 = DIFF(lpNode - lpMetaPath);
  302. n2 = DIFF(lpEndPath - lpNode);
  303. strField = strMetaPath.Mid(n1, n2 - 1);
  304. }
  305. }
  306. else
  307. {
  308. ASSERT(FALSE);
  309. DV_E_CLIPFORMAT;
  310. }
  311. }
  312. TRACEEOLID("Requested metabase path data: " << strField);
  313. int len = strField.GetLength() + 1;
  314. hr = pStream->Write(strField,
  315. (ocslen(strField) + 1) * sizeof(OLECHAR), &uWritten);
  316. ASSERT(SUCCEEDED(hr));
  317. return hr;
  318. }
  319. HRESULT
  320. CIISMBNode::BuildURL(
  321. OUT CComBSTR & bstrURL
  322. ) const
  323. /*++
  324. Routine Description:
  325. Recursively build up the URL from the current node
  326. and its parents.
  327. Arguments:
  328. CComBSTR & bstrURL : Returns URL
  329. Return Value:
  330. HRESULT
  331. --*/
  332. {
  333. HRESULT hr = S_OK;
  334. //
  335. // Prepend parent portion
  336. //
  337. CIISMBNode * pNode = GetParentNode();
  338. if (pNode)
  339. {
  340. hr = pNode->BuildURL(bstrURL);
  341. //
  342. // And our portion
  343. //
  344. if (SUCCEEDED(hr))
  345. {
  346. bstrURL.Append(_cszSeparator);
  347. bstrURL.Append(QueryNodeName());
  348. }
  349. return hr;
  350. }
  351. //
  352. // No parent node
  353. //
  354. ASSERT_MSG("No parent node");
  355. return E_UNEXPECTED;
  356. }
  357. BOOL
  358. CIISMBNode::OnLostInterface(
  359. IN OUT CError & err
  360. )
  361. /*++
  362. Routine Description:
  363. Deal with lost interface. Ask the user to reconnect.
  364. Arguments:
  365. CError & err : Error object
  366. Return Value:
  367. TRUE if the interface was successfully recreated.
  368. FALSE otherwise. If it tried and failed the error will
  369. --*/
  370. {
  371. AFX_MANAGE_STATE(::AfxGetStaticModuleState());
  372. CString str;
  373. str.Format(IDS_RECONNECT_WARNING, QueryMachineName());
  374. if (YesNoMessageBox(str))
  375. {
  376. //
  377. // Attempt to recreate the interface
  378. //
  379. err = CreateInterface(TRUE);
  380. return err.Succeeded();
  381. }
  382. return FALSE;
  383. }
  384. HRESULT
  385. CIISMBNode::DeleteNode(IResultData * pResult)
  386. {
  387. CError err;
  388. if (!NoYesMessageBox(IDS_CONFIRM_DELETE))
  389. return err;
  390. do
  391. {
  392. CComBSTR path;
  393. CMetaInterface * pInterface = QueryInterface();
  394. ASSERT(pInterface != NULL);
  395. err = BuildMetaPath(path);
  396. if (err.Failed())
  397. break;
  398. CMetaKey mk(pInterface, METADATA_MASTER_ROOT_HANDLE, METADATA_PERMISSION_WRITE);
  399. if (!mk.Succeeded())
  400. break;
  401. err = mk.DeleteKey(path);
  402. if (err.Failed())
  403. break;
  404. err = RemoveScopeItem();
  405. } while (FALSE);
  406. if (err.Failed())
  407. {
  408. DisplayError(err);
  409. }
  410. return err;
  411. }
  412. HRESULT
  413. CIISMBNode::EnumerateVDirs(HSCOPEITEM hParent, CIISService * pService)
  414. /*++
  415. Routine Description:
  416. Enumerate scope child items.
  417. Arguments:
  418. HSCOPEITEM hParent : Parent console handle
  419. CIISService * pService : Service type
  420. Return Value:
  421. HRESULT
  422. --*/
  423. {
  424. ASSERT_PTR(pService);
  425. CError err;
  426. CString strVRoot;
  427. CMetaEnumerator * pme = NULL;
  428. err = CreateEnumerator(pme);
  429. while (err.Succeeded())
  430. {
  431. CIISDirectory * pDir;
  432. err = pme->Next(strVRoot);
  433. if (err.Succeeded())
  434. {
  435. TRACEEOLID("Enumerating node: " << strVRoot);
  436. CChildNodeProps child(pme, strVRoot, WITH_INHERITANCE, FALSE);
  437. err = child.LoadData();
  438. DWORD dwWin32Error = err.Win32Error();
  439. if (err.Failed())
  440. {
  441. //
  442. // Filter out the non-fatal errors
  443. //
  444. switch(err.Win32Error())
  445. {
  446. case ERROR_ACCESS_DENIED:
  447. case ERROR_FILE_NOT_FOUND:
  448. case ERROR_PATH_NOT_FOUND:
  449. err.Reset();
  450. break;
  451. default:
  452. TRACEEOLID("Fatal error occurred " << err);
  453. }
  454. }
  455. if (err.Succeeded())
  456. {
  457. //
  458. // Skip non-virtual directories (that is, those with
  459. // inherited vrpaths)
  460. //
  461. if (!child.IsPathInherited())
  462. {
  463. //
  464. // Construct with full information.
  465. //
  466. pDir = new CIISDirectory(
  467. m_pOwner,
  468. pService,
  469. strVRoot,
  470. child.IsEnabledApplication(),
  471. child.QueryWin32Error(),
  472. child.GetRedirectedPath()
  473. );
  474. if (!pDir)
  475. {
  476. err = ERROR_NOT_ENOUGH_MEMORY;
  477. break;
  478. }
  479. err = pDir->AddToScopePane(hParent);
  480. }
  481. }
  482. }
  483. }
  484. SAFE_DELETE(pme);
  485. if (err.Win32Error() == ERROR_NO_MORE_ITEMS)
  486. {
  487. err.Reset();
  488. }
  489. if (err.Failed())
  490. {
  491. DisplayError(err);
  492. }
  493. // SetInterfaceError(err);
  494. return err;
  495. }
  496. BOOL
  497. CIISMBNode::GetPhysicalPath(
  498. LPCTSTR metaPath,
  499. CString & alias,
  500. CString & physicalPath
  501. )
  502. /*++
  503. Routine Description:
  504. Build a physical path for the current node. Starting with the current
  505. node, walk up the tree appending node names until a virtual directory
  506. with a real physical path is found
  507. Arguments:
  508. CString & physicalPath : Returns file path
  509. Return Value:
  510. Pointer to path
  511. --*/
  512. {
  513. if (CMetabasePath::IsMasterInstance(metaPath))
  514. return FALSE;
  515. BOOL fInherit = FALSE;
  516. CMetaInterface * pInterface = QueryInterface();
  517. ASSERT(pInterface != NULL);
  518. CMetaKey mk(pInterface);
  519. CError err(mk.QueryValue(
  520. MD_VR_PATH,
  521. physicalPath,
  522. &fInherit,
  523. metaPath
  524. ));
  525. if (err.Failed())
  526. {
  527. CString lastNode;
  528. CMetabasePath::GetLastNodeName(metaPath, lastNode);
  529. PathAppend(lastNode.GetBuffer(MAX_PATH), alias);
  530. lastNode.ReleaseBuffer();
  531. CString buf(metaPath);
  532. if (NULL == CMetabasePath::ConvertToParentPath(buf))
  533. {
  534. return FALSE;
  535. }
  536. else if (GetPhysicalPath(buf, lastNode, physicalPath))
  537. {
  538. return TRUE;
  539. }
  540. }
  541. if (!alias.IsEmpty())
  542. {
  543. PathAppend(physicalPath.GetBuffer(MAX_PATH), alias);
  544. physicalPath.ReleaseBuffer();
  545. }
  546. return TRUE;
  547. }
  548. HRESULT
  549. CIISMBNode::CleanResult(IResultData * lpResultData)
  550. {
  551. CError err;
  552. if (!m_ResultItems.IsEmpty())
  553. {
  554. POSITION pos = m_ResultItems.GetHeadPosition();
  555. while (pos != NULL)
  556. {
  557. CIISFileName * pNode = m_ResultItems.GetNext(pos);
  558. err = lpResultData->DeleteItem(pNode->m_hResultItem, 0);
  559. if (err.Failed())
  560. {
  561. ASSERT(FALSE);
  562. break;
  563. }
  564. delete pNode;
  565. }
  566. m_ResultItems.RemoveAll();
  567. }
  568. return err;
  569. }
  570. HRESULT
  571. CIISMBNode::EnumerateResultPane_(
  572. BOOL fExpand,
  573. IHeaderCtrl * lpHeader,
  574. IResultData * lpResultData,
  575. CIISService * pService
  576. )
  577. {
  578. CError err;
  579. if (HasFileSystemFiles())
  580. {
  581. if (fExpand)
  582. {
  583. do
  584. {
  585. CString dir;
  586. CComBSTR root;
  587. BuildMetaPath(root);
  588. CString physPath, alias;
  589. GetPhysicalPath(CString(root), alias, physPath);
  590. if (pService->IsLocal() || PathIsUNC(physPath))
  591. {
  592. dir = physPath;
  593. }
  594. else
  595. {
  596. ::MakeUNCPath(dir, pService->QueryMachineName(), physPath);
  597. }
  598. dir.TrimLeft();
  599. dir.TrimRight();
  600. if (dir.IsEmpty())
  601. {
  602. break;
  603. }
  604. if (PathIsUNCServerShare(dir))
  605. {
  606. CString server, share;
  607. int idx = dir.ReverseFind(_T('\\'));
  608. ASSERT(idx != -1);
  609. server = dir.Left(idx);
  610. share = dir.Mid(++idx);
  611. LPBYTE pbuf = NULL;
  612. NET_API_STATUS rc = NetShareGetInfo((LPTSTR)(LPCTSTR)server, (LPTSTR)(LPCTSTR)share, 0, &pbuf);
  613. if (NERR_Success == rc)
  614. {
  615. NetApiBufferFree(pbuf);
  616. }
  617. else
  618. {
  619. err = ERROR_BAD_NETPATH;
  620. break;
  621. }
  622. }
  623. dir += _T("\\*");
  624. WIN32_FIND_DATA w32data;
  625. HANDLE hFind = ::FindFirstFile(dir, &w32data);
  626. if (hFind == INVALID_HANDLE_VALUE)
  627. {
  628. err.GetLastWinError();
  629. ASSERT(FALSE);
  630. break;
  631. }
  632. do
  633. {
  634. LPCTSTR name = w32data.cFileName;
  635. if ((w32data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0)
  636. {
  637. CIISFileName * pNode = new CIISFileName(
  638. GetOwner(),
  639. pService,
  640. w32data.dwFileAttributes,
  641. name,
  642. NULL);
  643. if (!pNode)
  644. {
  645. err = ERROR_NOT_ENOUGH_MEMORY;
  646. break;
  647. }
  648. RESULTDATAITEM ri;
  649. ::ZeroMemory(&ri, sizeof(ri));
  650. ri.mask = RDI_STR | RDI_IMAGE | RDI_PARAM;
  651. ri.str = MMC_CALLBACK;
  652. ri.nImage = pNode->QueryImage();
  653. ri.lParam = (LPARAM)pNode;
  654. err = lpResultData->InsertItem(&ri);
  655. if (err.Succeeded())
  656. {
  657. pNode->SetScopeItem(m_hScopeItem);
  658. pNode->SetResultItem(ri.itemID);
  659. m_ResultItems.AddTail(pNode);
  660. }
  661. else
  662. {
  663. delete pNode;
  664. }
  665. }
  666. } while (err.Succeeded() && FindNextFile(hFind, &w32data));
  667. FindClose(hFind);
  668. } while (FALSE);
  669. }
  670. else
  671. {
  672. RemoveResultItems();
  673. }
  674. }
  675. ASSERT(err.Succeeded());
  676. return err;
  677. }
  678. void
  679. CIISMBNode::RemoveResultItems()
  680. {
  681. if (!m_ResultItems.IsEmpty())
  682. {
  683. POSITION pos = m_ResultItems.GetHeadPosition();
  684. while (pos != NULL)
  685. {
  686. CIISFileName * pNode = m_ResultItems.GetNext(pos);
  687. delete pNode;
  688. }
  689. m_ResultItems.RemoveAll();
  690. }
  691. }
  692. HRESULT
  693. CIISMBNode::EnumerateWebDirs(HSCOPEITEM hParent, CIISService * pService)
  694. /*++
  695. Routine Description:
  696. Enumerate scope file system child items.
  697. Arguments:
  698. HSCOPEITEM hParent : Parent console handle
  699. CIISService * pService : Service type
  700. Return Value:
  701. HRESULT
  702. --*/
  703. {
  704. ASSERT_PTR(pService);
  705. CError err;
  706. do
  707. {
  708. CString dir;
  709. CComBSTR root;
  710. BuildMetaPath(root);
  711. CString physPath, alias;
  712. GetPhysicalPath(CString(root), alias, physPath);
  713. if (pService->IsLocal() || PathIsUNC(physPath))
  714. {
  715. dir = physPath;
  716. }
  717. else
  718. {
  719. ::MakeUNCPath(dir, pService->QueryMachineName(), physPath);
  720. }
  721. dir.TrimLeft();
  722. dir.TrimRight();
  723. if (dir.IsEmpty())
  724. {
  725. break;
  726. }
  727. // Prepare for target machine metabase lookup
  728. BOOL fCheckMetabase = TRUE;
  729. CMetaKey mk(QueryInterface(), root, METADATA_PERMISSION_READ, METADATA_MASTER_ROOT_HANDLE);
  730. CError errMB(mk.QueryResult());
  731. if (errMB.Win32Error() == ERROR_PATH_NOT_FOUND)
  732. {
  733. //
  734. // Metabase path not found, not a problem.
  735. //
  736. fCheckMetabase = FALSE;
  737. errMB.Reset();
  738. }
  739. // We could have vroot pointed to target machine, or to another remote machine.
  740. // Check if this resource is available and we have access to this resource
  741. if (PathIsUNC(dir))
  742. {
  743. CString server, user, password;
  744. server = PathFindNextComponent(dir);
  745. int n = server.Find(_T('\\'));
  746. if (n != -1)
  747. {
  748. server = server.Left(n);
  749. }
  750. user = QueryInterface()->QueryAuthInfo()->QueryUserName();
  751. password = QueryInterface()->QueryAuthInfo()->QueryPassword();
  752. if (server.CompareNoCase(pService->QueryMachineName()) != 0)
  753. {
  754. // non-local resource, get connection credentials
  755. if (fCheckMetabase)
  756. {
  757. err = mk.QueryValue(MD_VR_USERNAME, user);
  758. if (err.Succeeded())
  759. {
  760. err = mk.QueryValue(MD_VR_PASSWORD, password);
  761. }
  762. // these credentials could be empty. try defaults
  763. err.Reset();
  764. }
  765. }
  766. // Add use for this resource
  767. NETRESOURCE nr;
  768. nr.dwType = RESOURCETYPE_DISK;
  769. nr.lpLocalName = NULL;
  770. nr.lpRemoteName = (LPTSTR)(LPCTSTR)dir;
  771. nr.lpProvider = NULL;
  772. // Empty strings below mean no password, which is wrong. NULLs mean
  773. // default user and default password -- this could work better for local case.
  774. LPCTSTR p1 = password, p2 = user;
  775. if (password.IsEmpty())
  776. {
  777. p1 = NULL;
  778. }
  779. if (user.IsEmpty())
  780. {
  781. p2 = NULL;
  782. }
  783. DWORD rc = WNetAddConnection2(&nr, p1, p2, 0);
  784. if (NO_ERROR != rc)
  785. {
  786. err = rc;
  787. break;
  788. }
  789. }
  790. #if 0
  791. // This is obsolete now
  792. if (PathIsUNCServerShare(dir))
  793. {
  794. CString server, share;
  795. int idx = dir.ReverseFind(_T('\\'));
  796. ASSERT(idx != -1);
  797. server = dir.Left(idx);
  798. share = dir.Mid(++idx);
  799. LPBYTE pbuf = NULL;
  800. NET_API_STATUS rc = NetShareGetInfo((LPTSTR)(LPCTSTR)server, (LPTSTR)(LPCTSTR)share, 0, &pbuf);
  801. if (NERR_Success == rc)
  802. {
  803. NetApiBufferFree(pbuf);
  804. }
  805. else
  806. {
  807. err = ERROR_BAD_NETPATH;
  808. break;
  809. }
  810. }
  811. #endif
  812. dir += _T("\\*");
  813. WIN32_FIND_DATA w32data;
  814. HANDLE hFind = ::FindFirstFile(dir, &w32data);
  815. if (hFind == INVALID_HANDLE_VALUE)
  816. {
  817. err.GetLastWinError();
  818. break;
  819. }
  820. do
  821. {
  822. LPCTSTR name = w32data.cFileName;
  823. if ( (w32data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0
  824. && lstrcmp(name, _T(".")) != 0
  825. && lstrcmp(name, _T("..")) != 0
  826. )
  827. {
  828. CIISFileName * pNode = new CIISFileName(m_pOwner,
  829. pService, w32data.dwFileAttributes, name, NULL);
  830. if (!pNode)
  831. {
  832. err = ERROR_NOT_ENOUGH_MEMORY;
  833. break;
  834. }
  835. if (fCheckMetabase)
  836. {
  837. errMB = mk.DoesPathExist(w32data.cFileName);
  838. if (errMB.Succeeded())
  839. {
  840. //
  841. // Match up with metabase properties. If the item
  842. // is found in the metabase with a non-inherited vrpath,
  843. // than a virtual root with this name exists, and this
  844. // file/directory should not be shown.
  845. //
  846. CString vrpath;
  847. BOOL f = FALSE;
  848. DWORD attr = 0;
  849. errMB = mk.QueryValue(MD_VR_PATH, vrpath, NULL, w32data.cFileName, &attr);
  850. if (errMB.Succeeded() && (attr & METADATA_ISINHERITED) == 0)
  851. {
  852. TRACEEOLID("file/directory exists as vroot -- tossing" << w32data.cFileName);
  853. delete pNode;
  854. continue;
  855. }
  856. }
  857. }
  858. err = pNode->AddToScopePane(hParent);
  859. }
  860. } while (err.Succeeded() && FindNextFile(hFind, &w32data));
  861. FindClose(hFind);
  862. } while (FALSE);
  863. if (err.Failed())
  864. {
  865. DisplayError(err);
  866. }
  867. return err;
  868. }
  869. HRESULT
  870. CIISMBNode::CreateEnumerator(CMetaEnumerator *& pEnum)
  871. /*++
  872. Routine Description:
  873. Create enumerator object for the current path. Requires interface
  874. to already be initialized
  875. Arguments:
  876. CMetaEnumerator *& pEnum : Returns enumerator
  877. Return Value:
  878. HRESULT
  879. --*/
  880. {
  881. ASSERT(pEnum == NULL);
  882. ASSERT(m_hScopeItem != NULL);
  883. CComBSTR bstrPath;
  884. CError err(BuildMetaPath(bstrPath));
  885. if (err.Succeeded())
  886. {
  887. TRACEEOLID("Build metabase path: " << bstrPath);
  888. BOOL fContinue = TRUE;
  889. while(fContinue)
  890. {
  891. fContinue = FALSE;
  892. pEnum = new CMetaEnumerator(QueryInterface(), bstrPath);
  893. err = pEnum ? pEnum->QueryResult() : ERROR_NOT_ENOUGH_MEMORY;
  894. if (IsLostInterface(err))
  895. {
  896. SAFE_DELETE(pEnum);
  897. fContinue = OnLostInterface(err);
  898. }
  899. }
  900. }
  901. return err;
  902. }
  903. /* virtual */
  904. HRESULT
  905. CIISMBNode::Refresh(BOOL fReEnumerate)
  906. /*++
  907. Routine Description:
  908. Refresh current node, and optionally re-enumerate child objects
  909. Arguments:
  910. BOOL fReEnumerate : If true, kill child objects, and re-enumerate
  911. --*/
  912. {
  913. CError err;
  914. //
  915. // Set MFC state for wait cursor
  916. //
  917. AFX_MANAGE_STATE(::AfxGetStaticModuleState());
  918. CWaitCursor wait;
  919. if (fReEnumerate)
  920. {
  921. //
  922. // Kill child objects
  923. //
  924. TRACEEOLID("Killing child objects");
  925. ASSERT(m_hScopeItem != NULL);
  926. err = RemoveChildren(m_hScopeItem);
  927. if (err.Succeeded())
  928. {
  929. err = EnumerateScopePane(m_hScopeItem);
  930. }
  931. }
  932. if (err.Succeeded())
  933. {
  934. //
  935. // Refresh current node
  936. //
  937. err = RefreshData();
  938. if (err.Succeeded())
  939. {
  940. err = RefreshDisplay();
  941. }
  942. }
  943. return err;
  944. }
  945. /* virtual */
  946. HRESULT
  947. CIISMBNode::GetResultViewType(
  948. OUT LPOLESTR * lplpViewType,
  949. OUT long * lpViewOptions
  950. )
  951. /*++
  952. Routine Description:
  953. If we have an URL built up, display our result view as that URL,
  954. and destroy it. This is done when 'browsing' a metabase node.
  955. The derived class will build the URL, and reselect the node.
  956. Arguments:
  957. BSTR * lplpViewType : Return view type here
  958. long * lpViewOptions : View options
  959. Return Value:
  960. S_FALSE to use default view type, S_OK indicates the
  961. view type is returned in *ppViewType
  962. --*/
  963. {
  964. if (m_bstrURL.Length())
  965. {
  966. *lpViewOptions = MMC_VIEW_OPTIONS_NONE;
  967. *lplpViewType = (LPOLESTR)::CoTaskMemAlloc(
  968. (m_bstrURL.Length() + 1) * sizeof(WCHAR)
  969. );
  970. if (*lplpViewType)
  971. {
  972. lstrcpy(*lplpViewType, m_bstrURL);
  973. //
  974. // Destroy URL so we get a normal result view next time
  975. //
  976. m_bstrURL.Empty();
  977. m_fSkipEnumResult = TRUE;
  978. return S_OK;
  979. }
  980. return HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
  981. }
  982. //
  983. // No URL waiting -- use standard result view
  984. //
  985. return CIISObject::GetResultViewType(lplpViewType, lpViewOptions);
  986. }
  987. HRESULT
  988. ShellExecuteDirectory(
  989. IN LPCTSTR lpszCommand,
  990. IN LPCTSTR lpszOwner,
  991. IN LPCTSTR lpszDirectory
  992. )
  993. /*++
  994. Routine Description:
  995. Shell Open or explore on a given directory path
  996. Arguments:
  997. LPCTSTR lpszCommand : "open" or "explore"
  998. LPCTSTR lpszOwner : Owner server
  999. LPCTSTR lpszDirectory : Directory path
  1000. Return Value:
  1001. Error return code.
  1002. --*/
  1003. {
  1004. CString strDir;
  1005. if (::IsServerLocal(lpszOwner) || ::IsUNCName(lpszDirectory))
  1006. {
  1007. //
  1008. // Local directory, or already a unc path
  1009. //
  1010. strDir = lpszDirectory;
  1011. }
  1012. else
  1013. {
  1014. ::MakeUNCPath(strDir, lpszOwner, lpszDirectory);
  1015. }
  1016. TRACEEOLID("Attempting to " << lpszCommand << " Path: " << strDir);
  1017. CError err;
  1018. {
  1019. //
  1020. // AFX_MANAGE_STATE required for wait cursor
  1021. //
  1022. AFX_MANAGE_STATE(::AfxGetStaticModuleState() );
  1023. CWaitCursor wait;
  1024. if (::ShellExecute(
  1025. NULL,
  1026. lpszCommand,
  1027. strDir,
  1028. NULL,
  1029. _T(""),
  1030. SW_SHOW
  1031. ) <= (HINSTANCE)32)
  1032. {
  1033. err.GetLastWinError();
  1034. }
  1035. }
  1036. return err;
  1037. }
  1038. HRESULT
  1039. CIISMBNode::Command(
  1040. IN long lCommandID,
  1041. IN CSnapInObjectRootBase * pObj,
  1042. IN DATA_OBJECT_TYPES type
  1043. )
  1044. /*++
  1045. Routine Description:
  1046. Handle command from context menu.
  1047. Arguments:
  1048. long lCommandID : Command ID
  1049. CSnapInObjectRootBase * pObj : Base object
  1050. DATA_OBJECT_TYPES type : Data object type
  1051. Return Value:
  1052. HRESULT
  1053. --*/
  1054. {
  1055. AFX_MANAGE_STATE(::AfxGetStaticModuleState());
  1056. HRESULT hr = S_OK;
  1057. CError err = ERROR_NOT_ENOUGH_MEMORY;
  1058. switch (lCommandID)
  1059. {
  1060. case IDM_BROWSE:
  1061. //
  1062. // Build URL for this node, and force a re-select so as to change
  1063. // the result view
  1064. //
  1065. BuildURL(m_bstrURL);
  1066. if (m_bstrURL.Length())
  1067. {
  1068. //
  1069. // After selection, the browsed URL will come up in the result view
  1070. //
  1071. SelectScopeItem();
  1072. }
  1073. break;
  1074. //
  1075. // CODEWORK: Build path, and, using the explorer URL, put this stuff
  1076. // in the result view.
  1077. //
  1078. case IDM_OPEN:
  1079. {
  1080. CComBSTR meta_path;
  1081. CString phys_path, alias;
  1082. BuildMetaPath(meta_path);
  1083. if (GetPhysicalPath(meta_path, alias, phys_path))
  1084. {
  1085. hr = ShellExecuteDirectory(_T("open"), QueryMachineName(), phys_path);
  1086. }
  1087. }
  1088. break;
  1089. case IDM_EXPLORE:
  1090. {
  1091. CComBSTR meta_path;
  1092. CString phys_path, alias;
  1093. BuildMetaPath(meta_path);
  1094. if (GetPhysicalPath(meta_path, alias, phys_path))
  1095. {
  1096. TCHAR url[MAX_PATH];
  1097. DWORD len = MAX_PATH;
  1098. hr = UrlCreateFromPath(phys_path, url, &len, NULL);
  1099. m_bstrURL = url;
  1100. SelectScopeItem();
  1101. }
  1102. }
  1103. break;
  1104. case IDM_TASK_SECURITY_WIZARD:
  1105. {
  1106. CComBSTR path;
  1107. VERIFY(SUCCEEDED(BuildMetaPath(path)));
  1108. hr = RunSecurityWizard(QueryAuthInfo(),
  1109. QueryInterface(), CString(path),
  1110. IDB_WIZ_FTP_LEFT_SEC, IDB_WIZ_FTP_HEAD_SEC);
  1111. }
  1112. break;
  1113. //
  1114. // Pass on to base class
  1115. //
  1116. default:
  1117. hr = CIISObject::Command(lCommandID, pObj, type);
  1118. }
  1119. return hr;
  1120. }
  1121. HRESULT
  1122. CIISMBNode::OnPropertyChange(BOOL fScope, IResultData * pResult)
  1123. {
  1124. CError err;
  1125. err = Refresh(fScope);
  1126. if (err.Succeeded())
  1127. {
  1128. if ( fScope
  1129. && HasFileSystemFiles()
  1130. && !m_ResultItems.IsEmpty()
  1131. )
  1132. {
  1133. err = CleanResult(pResult);
  1134. if (err.Succeeded())
  1135. {
  1136. err = EnumerateResultPane(fScope, NULL, pResult);
  1137. }
  1138. }
  1139. else if (!fScope)
  1140. {
  1141. pResult->UpdateItem(m_hResultItem);
  1142. }
  1143. }
  1144. return err;
  1145. }
  1146. HRESULT
  1147. CIISMBNode::RemoveResultNode(CIISMBNode * pNode, IResultData * pResult)
  1148. {
  1149. CError err;
  1150. ASSERT(HasFileSystemFiles());
  1151. err = pResult->DeleteItem(pNode->m_hResultItem, 0);
  1152. if (err.Succeeded())
  1153. {
  1154. BOOL found = FALSE;
  1155. POSITION pos = m_ResultItems.GetHeadPosition();
  1156. while (pos != NULL)
  1157. {
  1158. if (m_ResultItems.GetNext(pos) == pNode)
  1159. {
  1160. found = TRUE;
  1161. break;
  1162. }
  1163. }
  1164. if (found)
  1165. {
  1166. m_ResultItems.RemoveAt(pos);
  1167. delete pNode;
  1168. }
  1169. }
  1170. return err;
  1171. }
  1172. // See FtpAddNew.cpp for the method CIISMBNode::AddFTPSite
  1173. // See WebAddNew.cpp for the method CIISMBNode::AddWebSite
  1174. // See add_app_pool.cpp for the method CIISMBNode::AddAppPool