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.

2887 lines
55 KiB

  1. fs/*++
  2. Copyright (c) 1994-1998 Microsoft Corporation
  3. Module Name :
  4. pwiz.cpp
  5. Abstract:
  6. IIS Security Wizard
  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 "common.h"
  18. #include "inetprop.h"
  19. #include "resource.h"
  20. #include "pwiz.h"
  21. #include <aclapi.h>
  22. //#include <ntseapi.h>
  23. #include <shlwapi.h>
  24. BOOL CheckIfParentHasAccess(CComAuthInfo *pAuthInfo, CString csMetabaseNode);
  25. BOOL ConvertToServiceLevelPath(CString & strMetaPath);
  26. //
  27. // IIS Security Template Class
  28. //
  29. // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  30. //
  31. // Package of access rights granted for "READ" access
  32. //
  33. #define ACCMASK_READ_FLAGS (0L\
  34. | FILE_READ_DATA\
  35. | READ_CONTROL\
  36. | SYNCHRONIZE\
  37. | FILE_READ_ATTRIBUTES\
  38. | FILE_READ_EA\
  39. )
  40. //
  41. // Package of access rights granted for "WRITE" access
  42. //
  43. // Note: This includes "delete" because the web service assumes
  44. // "delete" when granting write access. This differs from
  45. // the norm.
  46. //
  47. #define ACCMASK_WRITE_FLAGS (0L\
  48. | FILE_WRITE_DATA\
  49. | FILE_APPEND_DATA\
  50. | DELETE\
  51. | FILE_WRITE_ATTRIBUTES\
  52. | FILE_WRITE_EA\
  53. )
  54. //
  55. // Package of access rights granted for "EXECUTE" access
  56. //
  57. #define ACCMASK_EXEC_FLAGS (0L\
  58. | FILE_EXECUTE\
  59. )
  60. //
  61. // Package of access rights granted for "DIR BROWSE" access
  62. //
  63. //#define ACCMASK_DIRBROWSE_FLAGS (0L\
  64. // | DS_LIST_OBJECT\
  65. // )
  66. //
  67. // Package of access rights granted for "FULL CONTROL" access
  68. //
  69. #define ACCMASK_ADMIN_FLAGS (0L\
  70. | STANDARD_RIGHTS_ALL\
  71. | FILE_READ_DATA\
  72. | FILE_WRITE_DATA\
  73. | FILE_APPEND_DATA\
  74. | FILE_READ_EA\
  75. | FILE_WRITE_EA\
  76. | FILE_EXECUTE\
  77. | FILE_ADD_FILE\
  78. | FILE_ADD_SUBDIRECTORY\
  79. | FILE_READ_ATTRIBUTES\
  80. | FILE_WRITE_ATTRIBUTES\
  81. | FILE_LIST_DIRECTORY\
  82. | FILE_DELETE_CHILD\
  83. | FILE_TRAVERSE\
  84. | ACTRL_DS_LIST_OBJECT\
  85. )
  86. //
  87. // Package of access rights granted for "Everyone"
  88. #define ACC_MASK_EVERYONE_FLAGS (0L\
  89. | ACCMASK_READ_FLAGS\
  90. | ACCMASK_EXEC_FLAGS\
  91. )
  92. //
  93. //
  94. // Access permission bit strings
  95. //
  96. FLAGTOSTRING fsAccessPerms[] =
  97. {
  98. { MD_ACCESS_READ, IDS_PERMS_READ, TRUE },
  99. { MD_ACCESS_WRITE, IDS_PERMS_WRITE, TRUE },
  100. { MD_ACCESS_SCRIPT, IDS_PERMS_SCRIPT, TRUE },
  101. { MD_ACCESS_EXECUTE, IDS_PERMS_EXECUTE, TRUE },
  102. };
  103. //
  104. // Access mask bit strings
  105. //
  106. FLAGTOSTRING fsAclFlags[] =
  107. {
  108. { FILE_READ_DATA, IDS_ACL_READ, TRUE },
  109. { READ_CONTROL, IDS_ACL_READ_CONTROL, TRUE },
  110. { FILE_READ_ATTRIBUTES, IDS_ACL_READ_ATTRIB, TRUE },
  111. { FILE_READ_EA, IDS_ACL_READ_PROP, TRUE },
  112. { FILE_WRITE_DATA, IDS_ACL_WRITE, TRUE },
  113. { FILE_APPEND_DATA, IDS_ACL_APPEND, TRUE },
  114. { DELETE, IDS_ACL_DELETE, TRUE },
  115. { FILE_WRITE_ATTRIBUTES, IDS_ACL_WRITE_ATTRIB, TRUE },
  116. { FILE_WRITE_EA, IDS_ACL_WRITE_PROP, TRUE },
  117. { FILE_EXECUTE, IDS_ACL_EXECUTE, TRUE },
  118. // { DS_LIST_CONTENTS, IDS_ACL_LIST_OBJECT, TRUE },
  119. };
  120. CIISSecurityTemplate::CIISSecurityTemplate(
  121. IN CMetaKey * pKey,
  122. IN LPCTSTR lpszMDPath,
  123. IN BOOL fInherit
  124. )
  125. /*++
  126. Routine Description:
  127. Construct from open key
  128. Arguments:
  129. const CMetaKey * pKey : Open key
  130. LPCTSTR lpszMDPath : Path
  131. BOOL fInherit : TRUE to inherit properties
  132. Return Value:
  133. N/A
  134. --*/
  135. : CMetaProperties(pKey, lpszMDPath),
  136. m_dwAccessPerms(0L),
  137. m_dlProperties(),
  138. m_strlSummary(),
  139. m_ipl()
  140. {
  141. //
  142. // Set base class member
  143. //
  144. m_fInherit = fInherit;
  145. //
  146. // Managed Properties
  147. //
  148. m_dlProperties.AddTail(MD_ACCESS_PERM);
  149. m_dlProperties.AddTail(MD_IP_SEC);
  150. }
  151. /* virtual */
  152. void
  153. CIISSecurityTemplate::ParseFields()
  154. /*++
  155. Routine Description:
  156. Break into fields.
  157. Arguments:
  158. None.
  159. Return Value:
  160. None.
  161. --*/
  162. {
  163. BEGIN_PARSE_META_RECORDS(m_dwNumEntries, m_pbMDData)
  164. HANDLE_META_RECORD(MD_ACCESS_PERM, m_dwAccessPerms)
  165. HANDLE_META_RECORD(MD_IP_SEC, m_ipl)
  166. END_PARSE_META_RECORDS
  167. //
  168. // If "execute" or "script" is on, read should be as well (makes
  169. // little sense otherwise)
  170. //
  171. if (IS_FLAG_SET(MP_V(m_dwAccessPerms), (MD_ACCESS_EXECUTE | MD_ACCESS_SCRIPT)))
  172. {
  173. SET_FLAG(MP_V(m_dwAccessPerms), MD_ACCESS_READ);
  174. }
  175. }
  176. /* virtual */
  177. HRESULT
  178. CIISSecurityTemplate::ApplySettings(
  179. IN BOOL fUseTemplate,
  180. IN CComAuthInfo * pAuthInfo,
  181. IN LPCTSTR lpszMDPath
  182. )
  183. {
  184. BOOL fWriteProperties = TRUE;
  185. CMetaKey mk(pAuthInfo, lpszMDPath, METADATA_PERMISSION_WRITE);
  186. CError err(mk.QueryResult());
  187. if (err.Win32Error() == ERROR_PATH_NOT_FOUND)
  188. {
  189. if (fUseTemplate)
  190. {
  191. //
  192. // Create the path
  193. //
  194. err = mk.CreatePathFromFailedOpen();
  195. if (err.Succeeded())
  196. {
  197. err = mk.ReOpen(METADATA_PERMISSION_WRITE);
  198. }
  199. }
  200. else
  201. {
  202. //
  203. // No need to delete properties; everything's already
  204. // inherited.
  205. //
  206. fWriteProperties = FALSE;
  207. err.Reset();
  208. }
  209. }
  210. if (fWriteProperties)
  211. {
  212. do
  213. {
  214. BREAK_ON_ERR_FAILURE(err);
  215. if (fUseTemplate)
  216. {
  217. //
  218. // Write values from template
  219. //
  220. err = mk.SetValue(
  221. MD_ACCESS_PERM,
  222. m_dwAccessPerms
  223. );
  224. BREAK_ON_ERR_FAILURE(err);
  225. err = mk.SetValue(MD_IP_SEC, m_ipl);
  226. BREAK_ON_ERR_FAILURE(err);
  227. }
  228. else
  229. {
  230. //
  231. // We're going to use inheritance, so delete
  232. // the values that might exist here
  233. //
  234. ASSERT(m_dlProperties.GetCount() > 0);
  235. POSITION pos = m_dlProperties.GetHeadPosition();
  236. while(pos)
  237. {
  238. DWORD dwID = m_dlProperties.GetNext(pos);
  239. err = mk.DeleteValue(dwID);
  240. if (err.HResult() == MD_ERROR_DATA_NOT_FOUND)
  241. {
  242. //
  243. // That's ok
  244. //
  245. err.Reset();
  246. }
  247. if (err.Failed())
  248. {
  249. break;
  250. }
  251. }
  252. }
  253. }
  254. while(FALSE);
  255. }
  256. return err;
  257. }
  258. void
  259. CIISSecurityTemplate::AddSummaryString(
  260. LPCTSTR szTextItem,
  261. int cIndentLevel
  262. )
  263. /*++
  264. Routine Description:
  265. Helper function to add strings to the summary
  266. Arguments:
  267. LPCTSTR szTextItem : String to be added
  268. int cIndentLevel : Indentation level
  269. Return Value:
  270. None
  271. --*/
  272. {
  273. CString str(szTextItem);
  274. //
  275. // Add a tab at the beginning of each string for each
  276. // level of indentation requested
  277. //
  278. for (int i = 0; i < cIndentLevel; ++i)
  279. {
  280. str = _T("\t") + str;
  281. }
  282. m_strlSummary.AddTail(str);
  283. }
  284. void
  285. CIISSecurityTemplate::AddSummaryString(
  286. UINT nID, int cIndentLevel)
  287. /*++
  288. Routine Description:
  289. Helper function to add strings to the summary which are referred to
  290. by string table resource ID
  291. Arguments:
  292. UINT nID : Resource ID
  293. int cIndentLevel : Indentation level
  294. Return Value:
  295. None
  296. --*/
  297. {
  298. CString str;
  299. VERIFY(str.LoadString(nID));
  300. AddSummaryString(str, cIndentLevel);
  301. }
  302. /* virtual */
  303. void
  304. CIISSecurityTemplate::GenerateSummary(
  305. BOOL fUseTemplate,
  306. CComAuthInfo * pAuthInfo,
  307. LPCTSTR lpszMDPath
  308. )
  309. /*++
  310. Routine Description:
  311. Generate text summary of what's in the security template
  312. Notes:
  313. This doesn't clear the summary. It's the responsibility of
  314. the calling process to clear beforehand, otherwise the summary
  315. items get added at the end.
  316. The derived class is expected to add its own information
  317. --*/
  318. {
  319. //
  320. // Summarize Access Permissions:
  321. //
  322. int nIndentLevel = 0;
  323. AddSummaryString(IDS_PERMISSIONS, nIndentLevel++);
  324. if (m_dwAccessPerms == 0L)
  325. {
  326. AddSummaryString(IDS_SUMMARY_NONE, nIndentLevel);
  327. }
  328. else
  329. {
  330. for (int i = 0; i < ARRAY_SIZE(fsAccessPerms); ++i)
  331. {
  332. if (IS_FLAG_SET(
  333. m_dwAccessPerms,
  334. fsAccessPerms[i].dwFlag
  335. ) == fsAccessPerms[i].fSet)
  336. {
  337. AddSummaryString(fsAccessPerms[i].nID, nIndentLevel);
  338. }
  339. }
  340. }
  341. //
  342. // Summarize IP Access Restrictions:
  343. //
  344. --nIndentLevel;
  345. AddSummaryString(IDS_ADDRESS_RESTRICTIONS, nIndentLevel++);
  346. if (MP_V(m_ipl).IsEmpty())
  347. {
  348. AddSummaryString(IDS_SUMMARY_NONE, nIndentLevel);
  349. }
  350. else
  351. {
  352. CObListPlus oblAccessList;
  353. BOOL fGrantByDefault;
  354. //
  355. // Get text version of ip access list for the summary
  356. //
  357. CError err(BuildIplOblistFromBlob(
  358. m_ipl,
  359. oblAccessList,
  360. fGrantByDefault
  361. ));
  362. if (err.Succeeded())
  363. {
  364. //
  365. // List default denied/granted state
  366. //
  367. AddSummaryString(
  368. fGrantByDefault ? IDS_SUMMARY_GRANTED : IDS_SUMMARY_DENIED,
  369. nIndentLevel
  370. );
  371. //
  372. // Enumerate restrictions (exceptions to the default)
  373. //
  374. CObListIter obli(oblAccessList);
  375. CIPAccessDescriptor * pAccess;
  376. CString str,
  377. strAddress,
  378. strGrpFormat,
  379. strGrantedFmt,
  380. strDeniedFmt;
  381. VERIFY(strGrantedFmt.LoadString(IDS_SPECIFIC_GRANTED));
  382. VERIFY(strDeniedFmt.LoadString(IDS_SPECIFIC_DENIED));
  383. VERIFY(strGrpFormat.LoadString(IDS_FMT_SECURITY));
  384. while (pAccess = (CIPAccessDescriptor *)obli.Next())
  385. {
  386. if (pAccess->IsDomainName())
  387. {
  388. strAddress = pAccess->QueryDomainName();
  389. }
  390. else if (pAccess->IsSingle())
  391. {
  392. strAddress = (LPCTSTR)pAccess->QueryIPAddress();
  393. }
  394. else
  395. {
  396. CString strIP, strMask;
  397. strAddress.Format(
  398. strGrpFormat,
  399. (LPCTSTR)pAccess->QueryIPAddress().QueryIPAddress(strIP),
  400. (LPCTSTR)pAccess->QuerySubnetMask().QueryIPAddress(strMask)
  401. );
  402. }
  403. str.Format(
  404. pAccess->HasAccess() ? strGrantedFmt : strDeniedFmt,
  405. strAddress
  406. );
  407. AddSummaryString(str, nIndentLevel);
  408. }
  409. }
  410. else
  411. {
  412. //
  413. // better than nothing
  414. //
  415. AddSummaryString(IDS_ADDRESS_IP, nIndentLevel);
  416. }
  417. }
  418. }
  419. //////////////////////////////////////////////////////////////////////
  420. CFTPSecurityTemplate::CFTPSecurityTemplate(
  421. IN CMetaKey * pKey,
  422. IN LPCTSTR lpszMDPath,
  423. IN BOOL fInherit
  424. )
  425. /*++
  426. Routine Description:
  427. Construct from open key
  428. Arguments:
  429. const CMetaKey * pKey : Open key
  430. LPCTSTR lpszMDPath : Path
  431. BOOL fInherit : TRUE to inherit values, FALSE if not
  432. Return Value:
  433. N/A
  434. --*/
  435. : CIISSecurityTemplate(pKey, lpszMDPath, fInherit),
  436. m_fAllowAnonymous(FALSE),
  437. m_fAnonymousOnly(FALSE)
  438. {
  439. //
  440. // Managed Properties
  441. //
  442. m_dlProperties.AddTail(MD_ALLOW_ANONYMOUS);
  443. m_dlProperties.AddTail(MD_ANONYMOUS_ONLY);
  444. }
  445. /* virtual */
  446. HRESULT
  447. CFTPSecurityTemplate::LoadData()
  448. /*++
  449. Routine Description:
  450. LoadData() base class override
  451. Arguments:
  452. None
  453. Return Value:
  454. HRESULT
  455. Notes:
  456. The FTP wizard has an annoying idiosynchrasy: access authentication
  457. settings are per site, not per vdir. Therefore, they need to be set
  458. and fetched in a separate path, and not be set at all if not
  459. setting props on a site. What a pain...
  460. --*/
  461. {
  462. TRACEEOLID(m_strMetaPath);
  463. m_strMetaRoot = _T("Root");
  464. CError err(CIISSecurityTemplate::LoadData());
  465. if (lstrcmpi(m_strMetaRoot, g_cszRoot) == 0)
  466. {
  467. //
  468. // Fetch the anonymous access settings from
  469. // the instance node. Note: This explicit step
  470. // should only be necessary for templates, because
  471. // this would otherwise be picked up on inheritance.
  472. //
  473. ASSERT(!m_fInherit);
  474. m_strMetaRoot.Empty();
  475. err = CIISSecurityTemplate::LoadData();
  476. }
  477. return err;
  478. }
  479. /* virtual */
  480. HRESULT
  481. CWebSecurityTemplate::LoadData()
  482. /*++
  483. Routine Description:
  484. LoadData() base class override
  485. Arguments:
  486. None
  487. Return Value:
  488. HRESULT
  489. Notes:
  490. --*/
  491. {
  492. TRACEEOLID(m_strMetaPath);
  493. m_strMetaRoot = _T("Root");
  494. CError err(CIISSecurityTemplate::LoadData());
  495. return err;
  496. }
  497. /* virtual */
  498. void
  499. CFTPSecurityTemplate::ParseFields()
  500. /*++
  501. Routine Description:
  502. Break into fields.
  503. Arguments:
  504. None.
  505. Return Value:
  506. None.
  507. --*/
  508. {
  509. //
  510. // Fetch base class values
  511. //
  512. CIISSecurityTemplate::ParseFields();
  513. BEGIN_PARSE_META_RECORDS(m_dwNumEntries, m_pbMDData)
  514. HANDLE_META_RECORD(MD_ALLOW_ANONYMOUS, m_fAllowAnonymous)
  515. HANDLE_META_RECORD(MD_ANONYMOUS_ONLY, m_fAnonymousOnly)
  516. END_PARSE_META_RECORDS
  517. }
  518. /* virtual */
  519. HRESULT
  520. CFTPSecurityTemplate::ApplySettings(
  521. BOOL fUseTemplates,
  522. CComAuthInfo * pAuthInfo,
  523. LPCTSTR lpszMDPath
  524. )
  525. {
  526. //
  527. // Write base class properties
  528. //
  529. CError err(CIISSecurityTemplate::ApplySettings(
  530. fUseTemplates,
  531. pAuthInfo,
  532. lpszMDPath
  533. ));
  534. if (err.Failed())
  535. {
  536. return err;
  537. }
  538. BOOL fWriteProperties = TRUE;
  539. CMetaKey mk(pAuthInfo, lpszMDPath, METADATA_PERMISSION_WRITE);
  540. err = mk.QueryResult();
  541. if (err.Win32Error() == ERROR_PATH_NOT_FOUND)
  542. {
  543. if (!fUseTemplates)
  544. {
  545. //
  546. // No need to delete properties; everything's already
  547. // inherited. Note that this is the only legit failure
  548. // case. If using a template, the base class must have
  549. // created the path by now.
  550. //
  551. fWriteProperties = FALSE;
  552. err.Reset();
  553. }
  554. }
  555. if (fWriteProperties)
  556. {
  557. do
  558. {
  559. if (mk.IsHomeDirectoryPath())
  560. {
  561. BREAK_ON_ERR_FAILURE(err);
  562. //
  563. // Path describes an instance path, which is the only
  564. // time we need to do anything here
  565. //
  566. err = mk.ConvertToParentPath(TRUE);
  567. BREAK_ON_ERR_FAILURE(err);
  568. if (fUseTemplates)
  569. {
  570. //
  571. // Write values from template
  572. //
  573. err = mk.SetValue(MD_ALLOW_ANONYMOUS, m_fAllowAnonymous);
  574. BREAK_ON_ERR_FAILURE(err);
  575. err = mk.SetValue(MD_ANONYMOUS_ONLY, m_fAnonymousOnly);
  576. }
  577. else
  578. {
  579. //
  580. // Inheritance case: delete authentication
  581. // values
  582. //
  583. mk.DeleteValue(MD_ALLOW_ANONYMOUS);
  584. mk.DeleteValue(MD_ANONYMOUS_ONLY);
  585. }
  586. }
  587. }
  588. while(FALSE);
  589. }
  590. return err;
  591. }
  592. /* virtual */
  593. void
  594. CFTPSecurityTemplate::GenerateSummary(
  595. BOOL fUseTemplates,
  596. CComAuthInfo * pAuthInfo,
  597. LPCTSTR lpszMDPath
  598. )
  599. {
  600. //
  601. // Authentication methods apply to instances only
  602. //
  603. if (CMetabasePath::IsHomeDirectoryPath(lpszMDPath))
  604. {
  605. //
  606. // Add private summary items
  607. //
  608. AddSummaryString(IDS_AUTHENTICATION_METHODS);
  609. //
  610. // Summarize Authentication Methods:
  611. //
  612. AddSummaryString(m_fAllowAnonymous ?
  613. IDS_AUTHENTICATION_ANONYMOUS : IDS_AUTHENTICATION_NO_ANONYMOUS, 1);
  614. if (m_fAllowAnonymous && m_fAnonymousOnly)
  615. {
  616. AddSummaryString(IDS_AUTHENTICATION_ANONYMOUS_ONLY, 1);
  617. }
  618. }
  619. //
  620. // Add base class summary
  621. //
  622. CIISSecurityTemplate::GenerateSummary(
  623. fUseTemplates, pAuthInfo, lpszMDPath);
  624. }
  625. ///////////////////////////////////////////////////////////////////////
  626. CWebSecurityTemplate::CWebSecurityTemplate(
  627. CMetaKey * pKey,
  628. LPCTSTR lpszMDPath,
  629. BOOL fInherit
  630. )
  631. /*++
  632. Routine Description:
  633. Construct from open key
  634. Arguments:
  635. const CMetaKey * pKey : Open key
  636. LPCTSTR lpszMDPath : Path
  637. BOOL fInherit : TRUE to inherit values, FALSE if not
  638. Return Value:
  639. N/A
  640. --*/
  641. : CIISSecurityTemplate(pKey, lpszMDPath, fInherit),
  642. m_dwAuthentication(MD_AUTH_ANONYMOUS),
  643. m_dwDirBrowsing(
  644. MD_DIRBROW_SHOW_DATE |
  645. MD_DIRBROW_SHOW_TIME |
  646. MD_DIRBROW_SHOW_SIZE |
  647. MD_DIRBROW_SHOW_EXTENSION
  648. )
  649. {
  650. //
  651. // Managed Properties
  652. //
  653. m_dlProperties.AddTail(MD_AUTHORIZATION);
  654. m_dlProperties.AddTail(MD_DIRECTORY_BROWSING);
  655. }
  656. /* virtual */
  657. void
  658. CWebSecurityTemplate::ParseFields()
  659. /*++
  660. Routine Description:
  661. Break into fields.
  662. Arguments:
  663. None.
  664. Return Value:
  665. None.
  666. --*/
  667. {
  668. //
  669. // Fetch base class values
  670. //
  671. CIISSecurityTemplate::ParseFields();
  672. BEGIN_PARSE_META_RECORDS(m_dwNumEntries, m_pbMDData)
  673. HANDLE_META_RECORD(MD_AUTHORIZATION, m_dwAuthentication)
  674. HANDLE_META_RECORD(MD_DIRECTORY_BROWSING, m_dwDirBrowsing)
  675. END_PARSE_META_RECORDS
  676. }
  677. /* virtual */
  678. HRESULT
  679. CWebSecurityTemplate::ApplySettings(
  680. BOOL fUseTemplates,
  681. CComAuthInfo * pAuthInfo,
  682. LPCTSTR lpszMDPath
  683. )
  684. /*++
  685. Routine Description:
  686. Apply the settings to the specified destination path
  687. Arguments:
  688. BOOL fUseTemplates : TRUE if the source is from a template,
  689. FALSE if using inheritance.
  690. LPCTSTR lpszServerName : Server name
  691. LPCTSTR lpszService : Service name
  692. DWORD dwInstance : Instance
  693. LPCTSTR lpszParent : Parent path (or NULL)
  694. LPCTSTR lpszAlias : Alias name (or NULL)
  695. Return Value:
  696. HRESULT
  697. --*/
  698. {
  699. //
  700. // Write base class properties
  701. //
  702. CError err(CIISSecurityTemplate::ApplySettings(
  703. fUseTemplates, pAuthInfo, lpszMDPath
  704. ));
  705. if (err.Failed())
  706. {
  707. return err;
  708. }
  709. BOOL fWriteProperties = TRUE;
  710. CMetaKey mk(
  711. pAuthInfo,
  712. lpszMDPath,
  713. METADATA_PERMISSION_WRITE
  714. );
  715. err = mk.QueryResult();
  716. if (err.Win32Error() == ERROR_PATH_NOT_FOUND)
  717. {
  718. if (!fUseTemplates)
  719. {
  720. //
  721. // No need to delete properties; everything's already
  722. // inherited. Note that this is the only legit failure
  723. // case. If using a template, the base class must have
  724. // created the path by now.
  725. //
  726. fWriteProperties = FALSE;
  727. err.Reset();
  728. }
  729. }
  730. if (fWriteProperties)
  731. {
  732. do
  733. {
  734. BREAK_ON_ERR_FAILURE(err);
  735. if (fUseTemplates)
  736. {
  737. //
  738. // Write values from template
  739. //
  740. err = mk.SetValue(
  741. MD_AUTHORIZATION,
  742. m_dwAuthentication
  743. );
  744. BREAK_ON_ERR_FAILURE(err);
  745. err = mk.SetValue(
  746. MD_DIRECTORY_BROWSING,
  747. m_dwDirBrowsing
  748. );
  749. BREAK_ON_ERR_FAILURE(err);
  750. }
  751. //
  752. // Nothing to do in the inheritance case, because the
  753. // base class knows which properties should be deleted
  754. //
  755. }
  756. while(FALSE);
  757. }
  758. return err;
  759. }
  760. //
  761. // Authentication bit strings
  762. //
  763. FLAGTOSTRING fsAuthentications[] =
  764. {
  765. { MD_AUTH_ANONYMOUS, IDS_AUTHENTICATION_ANONYMOUS, TRUE },
  766. { MD_AUTH_ANONYMOUS, IDS_AUTHENTICATION_NO_ANONYMOUS, FALSE },
  767. { MD_AUTH_BASIC, IDS_AUTHENTICATION_BASIC, TRUE },
  768. { MD_AUTH_MD5, IDS_AUTHENTICATION_DIGEST, TRUE },
  769. { MD_AUTH_NT, IDS_AUTHENTICATION_NT, TRUE },
  770. };
  771. /* virtual */
  772. void
  773. CWebSecurityTemplate::GenerateSummary(
  774. BOOL fUseTemplates,
  775. CComAuthInfo * pAuthInfo,
  776. LPCTSTR lpszMDPath
  777. )
  778. /*++
  779. Routine Description:
  780. Generate text summary of what's in the security template. Arguments are
  781. the same as ApplySettings(), so that the summary can reflect what will
  782. actually be set.
  783. Arguments:
  784. BOOL fUseTemplates : TRUE if the source is from a template,
  785. FALSE if using inheritance.
  786. LPCTSTR lpszServerName : Server name
  787. LPCTSTR lpszService : Service name
  788. DWORD dwInstance : Instance
  789. LPCTSTR lpszParent : Parent path (or NULL)
  790. LPCTSTR lpszAlias : Alias name (or NULL)
  791. Return Value:
  792. None
  793. --*/
  794. {
  795. AddSummaryString(IDS_AUTHENTICATION_METHODS);
  796. int i;
  797. //
  798. // Summarize Authentication Methods:
  799. //
  800. if (m_dwAuthentication == 0L)
  801. {
  802. AddSummaryString(IDS_SUMMARY_NONE, 1);
  803. }
  804. else
  805. {
  806. for (i = 0; i < ARRAY_SIZE(fsAuthentications); ++i)
  807. {
  808. if (IS_FLAG_SET(m_dwAuthentication, fsAuthentications[i].dwFlag) == fsAuthentications[i].fSet)
  809. {
  810. AddSummaryString(fsAuthentications[i].nID, 1);
  811. }
  812. }
  813. }
  814. AddSummaryString(IDS_DIRECTORY_BROWSE);
  815. if (IS_FLAG_SET(m_dwDirBrowsing, MD_DIRBROW_ENABLED))
  816. {
  817. AddSummaryString(IDS_DIR_BROWSE_ON, 1);
  818. }
  819. else
  820. {
  821. AddSummaryString(IDS_DIR_BROWSE_OFF, 1);
  822. }
  823. if (IS_FLAG_SET(m_dwDirBrowsing, MD_DIRBROW_LOADDEFAULT))
  824. {
  825. AddSummaryString(IDS_LOAD_DEFAULT_ON, 1);
  826. }
  827. else
  828. {
  829. AddSummaryString(IDS_LOAD_DEFAULT_OFF, 1);
  830. }
  831. //
  832. // Add base class summary
  833. //
  834. CIISSecurityTemplate::GenerateSummary(
  835. fUseTemplates, pAuthInfo, lpszMDPath);
  836. }
  837. ///////////////////////////////////////////////////////////////////////
  838. CIISSecWizSettings::CIISSecWizSettings(
  839. CComAuthInfo * pAuthInfo,
  840. LPCTSTR lpszMDPath
  841. )
  842. : CObjectPlus(),
  843. m_auth(pAuthInfo),
  844. m_strMDPath(lpszMDPath),
  845. m_fUseTemplate(TRUE),
  846. m_fSetAcls(FALSE),
  847. m_fReplaceAcls(FALSE),
  848. m_pist(NULL),
  849. m_hResult(S_OK)
  850. {
  851. }
  852. CIISSecWizSettings::~CIISSecWizSettings()
  853. /*++
  854. Routine Description:
  855. Destructor
  856. Arguments:
  857. N/A
  858. Return Value:
  859. N/A
  860. --*/
  861. {
  862. if (m_pist != NULL)
  863. {
  864. delete m_pist;
  865. }
  866. }
  867. HRESULT
  868. CIISSecWizSettings::FetchProperties(
  869. CMetaKey & mk,
  870. LPCTSTR lpszPath,
  871. BOOL fInherit
  872. )
  873. /*++
  874. Routine Description:
  875. Fetch metabase properties that are applicable for the security wizard
  876. Arguments:
  877. CMetaKey & mk : open key
  878. LPCTSTR lpszPath : Optional path
  879. BOOL fInherit : TRUE to inherit properties
  880. Return Value:
  881. HRESULT
  882. --*/
  883. {
  884. CError err(mk.QueryResult());
  885. if (err.Succeeded())
  886. {
  887. if (m_pist != NULL)
  888. {
  889. //
  890. // Clean up existing template data (must
  891. // have pressed "back")
  892. //
  893. delete m_pist;
  894. }
  895. //
  896. // Create security template by calling the provided
  897. // allocator (which allocates an object of the
  898. // derived class which is service-specific)
  899. //
  900. LPCTSTR p = lpszPath;
  901. if (p == NULL)
  902. {
  903. p = mk.QueryMetaPath();
  904. }
  905. CString spath, sname;
  906. CMetabasePath::GetServicePath(p, spath);
  907. CMetabasePath::GetLastNodeName(spath, sname);
  908. if (sname.CompareNoCase(SZ_MBN_WEB) == 0)
  909. {
  910. m_pist = new CWebSecurityTemplate(&mk, lpszPath, fInherit);
  911. }
  912. else if (sname.CompareNoCase(SZ_MBN_FTP) == 0)
  913. {
  914. m_pist = new CFTPSecurityTemplate(&mk, lpszPath, fInherit);
  915. }
  916. else
  917. {
  918. return ERROR_INVALID_PARAMETER;
  919. }
  920. if (m_pist == NULL)
  921. {
  922. err = ERROR_NOT_ENOUGH_MEMORY;
  923. }
  924. else
  925. {
  926. err = m_pist->LoadData();
  927. }
  928. }
  929. return err;
  930. }
  931. //
  932. // Permissions Wizard Source Page
  933. //
  934. // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  935. IMPLEMENT_DYNCREATE(CPWSource, CIISWizardPage)
  936. CPWSource::CPWSource(
  937. IN CIISSecWizSettings * pSettings
  938. )
  939. /*++
  940. Routine Description:
  941. Constructor
  942. Arguments:
  943. CIISSecWizSettings * pSettings : Settings
  944. Return Value:
  945. None
  946. --*/
  947. : CIISWizardPage(
  948. CPWSource::IDD, // Template
  949. IDS_PERMWIZ, // Caption
  950. HEADER_PAGE // Header
  951. ),
  952. m_pSettings(pSettings)
  953. {
  954. //{{AFX_DATA_INIT(CPWSource)
  955. m_nSource = RADIO_INHERITANCE;
  956. //}}AFX_DATA_INIT
  957. // ASSERT(m_pSettings);
  958. // ASSERT(!m_pSettings->m_strServer.IsEmpty());
  959. }
  960. CPWSource::~CPWSource()
  961. /*++
  962. Routine Description:
  963. Destructor
  964. Arguments:
  965. N/A
  966. Return Value:
  967. N/A
  968. --*/
  969. {
  970. }
  971. void
  972. CPWSource::DoDataExchange(
  973. IN CDataExchange * pDX
  974. )
  975. /*++
  976. Routine Description:
  977. Initialise/Store control data
  978. Arguments:
  979. CDataExchange * pDX - DDX/DDV control structure
  980. Return Value:
  981. None
  982. --*/
  983. {
  984. CIISWizardPage::DoDataExchange(pDX);
  985. //{{AFX_DATA_MAP(CPWSource)
  986. DDX_Radio(pDX, IDC_RADIO_INHERIT, m_nSource);
  987. //}}AFX_DATA_MAP
  988. }
  989. void
  990. CPWSource::SetControlStates()
  991. /*++
  992. Routine Description:
  993. Set the state of the control data
  994. Arguments:
  995. None
  996. Return Value:
  997. None
  998. --*/
  999. {
  1000. SetWizardButtons(PSWIZB_NEXT | PSWIZB_BACK);
  1001. }
  1002. //
  1003. // Message Map
  1004. //
  1005. BEGIN_MESSAGE_MAP(CPWSource, CIISWizardPage)
  1006. //{{AFX_MSG_MAP(CPWSource)
  1007. //}}AFX_MSG_MAP
  1008. END_MESSAGE_MAP()
  1009. //
  1010. // Message Handlers
  1011. //
  1012. // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  1013. BOOL
  1014. CPWSource::OnSetActive()
  1015. /*++
  1016. Routine Description:
  1017. Activation handler
  1018. Arguments:
  1019. None
  1020. Return Value:
  1021. TRUE for success, FALSE for failure
  1022. --*/
  1023. {
  1024. SetControlStates();
  1025. return CIISWizardPage::OnSetActive();
  1026. }
  1027. LRESULT
  1028. CPWSource::OnWizardNext()
  1029. /*++
  1030. Routine Description:
  1031. 'next' handler. Store the source specified, so the next
  1032. pages can skip or continue.
  1033. Arguments:
  1034. None
  1035. Return Value:
  1036. 0 to proceed, -1 to fail
  1037. --*/
  1038. {
  1039. UpdateData(TRUE);
  1040. m_pSettings->m_fUseTemplate = (m_nSource == RADIO_TEMPLATE);
  1041. if (!m_pSettings->m_fUseTemplate)
  1042. {
  1043. CError err;
  1044. CMetaKey mk(
  1045. m_pSettings->m_auth,
  1046. m_pSettings->m_strMDPath
  1047. );
  1048. if (mk.IsHomeDirectoryPath())
  1049. {
  1050. //
  1051. // Current path is a virtual server, and we're
  1052. // at the home directory. We need to back up
  1053. // twice.
  1054. //
  1055. err = mk.ConvertToParentPath(TRUE);
  1056. ASSERT(err.Succeeded());
  1057. }
  1058. //
  1059. // Convert to first parent path
  1060. //
  1061. err = mk.ConvertToParentPath(FALSE);
  1062. if (err.Succeeded())
  1063. {
  1064. err = m_pSettings->FetchProperties(mk, NULL, TRUE);
  1065. }
  1066. if (err.MessageBoxOnFailure())
  1067. {
  1068. return -1;
  1069. }
  1070. // Doing Inhert, so let's make sure
  1071. // that at least the node that we are inheriting from
  1072. // will have some sort of access...
  1073. if (FALSE == CheckIfParentHasAccess(m_pSettings->m_auth,m_pSettings->m_strMDPath))
  1074. {
  1075. // popup messagebox saying that parent that we are inheriting from
  1076. // does not give anyone access.
  1077. if (::AfxMessageBox(IDS_PARENT_PATH_MISSING_PERMISSIONS, MB_YESNO | MB_DEFBUTTON2 ) != IDYES)
  1078. {
  1079. return -1;
  1080. }
  1081. }
  1082. }
  1083. return CIISWizardPage::OnWizardNext();
  1084. }
  1085. //
  1086. // Permissions Wizard Template Page
  1087. //
  1088. // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  1089. IMPLEMENT_DYNCREATE(CPWTemplate, CIISWizardPage)
  1090. CPWTemplate::CPWTemplate(
  1091. IN CIISSecWizSettings * pSettings
  1092. )
  1093. /*++
  1094. Routine Description:
  1095. Constructor
  1096. Arguments:
  1097. CIISSecWizSettings * pSettings : Settings
  1098. Return Value:
  1099. None
  1100. --*/
  1101. : CIISWizardPage(
  1102. CPWTemplate::IDD, // Template
  1103. IDS_PERMWIZ, // Caption
  1104. HEADER_PAGE // Header
  1105. ),
  1106. m_pSettings(pSettings)
  1107. {
  1108. //{{AFX_DATA_INIT(CPWTemplate)
  1109. //}}AFX_DATA_INIT
  1110. ASSERT(m_pSettings);
  1111. // ASSERT(!m_pSettings->m_strServer.IsEmpty());
  1112. }
  1113. CPWTemplate::~CPWTemplate()
  1114. /*++
  1115. Routine Description:
  1116. Destructor
  1117. Arguments:
  1118. N/A
  1119. Return Value:
  1120. N/A
  1121. --*/
  1122. {
  1123. }
  1124. void
  1125. CPWTemplate::DoDataExchange(
  1126. IN CDataExchange * pDX
  1127. )
  1128. /*++
  1129. Routine Description:
  1130. Initialise/Store control data
  1131. Arguments:
  1132. CDataExchange * pDX - DDX/DDV control structure
  1133. Return Value:
  1134. None
  1135. --*/
  1136. {
  1137. CIISWizardPage::DoDataExchange(pDX);
  1138. //{{AFX_DATA_MAP(CPWTemplate)
  1139. DDX_Control(pDX, IDC_LIST_TEMPLATES, m_list_Templates);
  1140. DDX_Control(pDX, IDC_EDIT_DESCRIPTION, m_edit_Description);
  1141. //}}AFX_DATA_MAP
  1142. }
  1143. void
  1144. CPWTemplate::SetControlStates()
  1145. /*++
  1146. Routine Description:
  1147. Set the state of the control data
  1148. Arguments:
  1149. None
  1150. Return Value:
  1151. None
  1152. --*/
  1153. {
  1154. DWORD dwFlags = PSWIZB_BACK;
  1155. int nSel = m_list_Templates.GetCurSel();
  1156. if (nSel >= 0)
  1157. {
  1158. dwFlags |= PSWIZB_NEXT;
  1159. }
  1160. SetWizardButtons(dwFlags);
  1161. }
  1162. //
  1163. // Message Map
  1164. //
  1165. BEGIN_MESSAGE_MAP(CPWTemplate, CIISWizardPage)
  1166. //{{AFX_MSG_MAP(CPWTemplate)
  1167. ON_LBN_SELCHANGE(IDC_LIST_TEMPLATES, OnSelchangeListTemplates)
  1168. //}}AFX_MSG_MAP
  1169. END_MESSAGE_MAP()
  1170. //
  1171. // Message Handlers
  1172. //
  1173. // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  1174. BOOL
  1175. CPWTemplate::OnSetActive()
  1176. /*++
  1177. Routine Description:
  1178. Activation handler
  1179. Arguments:
  1180. None
  1181. Return Value:
  1182. TRUE to show the page, FALSE to skip it.
  1183. --*/
  1184. {
  1185. if (!m_pSettings->m_fUseTemplate)
  1186. {
  1187. return FALSE;
  1188. }
  1189. SetControlStates();
  1190. return CIISWizardPage::OnSetActive();
  1191. }
  1192. LRESULT
  1193. CPWTemplate::OnWizardNext()
  1194. /*++
  1195. Routine Description:
  1196. 'next' handler. Store the source specified, so the next
  1197. pages can skip or continue.
  1198. Arguments:
  1199. None
  1200. Return Value:
  1201. 0 to proceed, -1 to fail
  1202. --*/
  1203. {
  1204. UpdateData(TRUE);
  1205. int nSel = m_list_Templates.GetCurSel();
  1206. if (nSel < 0)
  1207. {
  1208. return -1;
  1209. }
  1210. CString strItem;
  1211. m_list_Templates.GetText(nSel, strItem);
  1212. //
  1213. // Fetch the template, which is the text up until the tab
  1214. // character
  1215. //
  1216. int nTab = strItem.Find(_T('\t'));
  1217. ASSERT(nTab >= 0);
  1218. if (nTab >= 0)
  1219. {
  1220. strItem.ReleaseBuffer(nTab);
  1221. }
  1222. TRACEEOLID(strItem);
  1223. //
  1224. // Read the properties from the selected template
  1225. //
  1226. CString strMDTemplates;
  1227. CString strMDTemplates2;
  1228. if (!CMetabasePath::GetServiceInfoPath(
  1229. m_pSettings->m_strMDPath,
  1230. strMDTemplates,
  1231. NULL
  1232. ))
  1233. {
  1234. ASSERT_MSG("Unable to generate info path");
  1235. return -1;
  1236. }
  1237. strMDTemplates = CMetabasePath(FALSE, strMDTemplates, SZ_MBN_TEMPLATES);
  1238. // at this point
  1239. // strMDTemplates=/LM/W3SVC/Info/Templates
  1240. //
  1241. // since this is a vdir, make it look like:
  1242. // strMDTemplates=/LM/W3SVC/Info/Templates/Secure Web Site
  1243. //
  1244. strMDTemplates = strMDTemplates + _T("/") + strItem;
  1245. CMetaKey mk(
  1246. m_pSettings->m_auth,
  1247. strMDTemplates
  1248. );
  1249. CError err(m_pSettings->FetchProperties(mk, NULL, FALSE));
  1250. if (err.MessageBoxOnFailure())
  1251. {
  1252. return -1;
  1253. }
  1254. return CIISWizardPage::OnWizardNext();
  1255. }
  1256. BOOL
  1257. CPWTemplate::OnInitDialog()
  1258. /*++
  1259. Routine Description:
  1260. WM_INITDIALOG handler. Initialize the dialog.
  1261. Arguments:
  1262. None.
  1263. Return Value:
  1264. TRUE if no focus is to be set automatically, FALSE if the focus
  1265. is already set.
  1266. --*/
  1267. {
  1268. CIISWizardPage::OnInitDialog();
  1269. //
  1270. // Assure the comments remain offscreen
  1271. //
  1272. m_list_Templates.SetTabStops(5000);
  1273. //
  1274. // Enumerate the existing templates
  1275. //
  1276. CError err;
  1277. CString strMDTemplates;
  1278. do
  1279. {
  1280. if (!CMetabasePath::GetServiceInfoPath(m_pSettings->m_strMDPath, strMDTemplates, NULL))
  1281. {
  1282. ASSERT_MSG("Unable to generate info path");
  1283. err = ERROR_PATH_NOT_FOUND;
  1284. break;
  1285. }
  1286. strMDTemplates = CMetabasePath(FALSE, strMDTemplates, SZ_MBN_TEMPLATES);
  1287. CMetaEnumerator mk(
  1288. m_pSettings->m_auth,
  1289. strMDTemplates
  1290. );
  1291. err = mk.QueryResult();
  1292. if (err.Failed())
  1293. {
  1294. break;
  1295. }
  1296. //
  1297. // Enumerate and add to the listbox.
  1298. //
  1299. CString strTemplate, strComment, strListItem;
  1300. while (err.Succeeded())
  1301. {
  1302. err = mk.Next(strTemplate);
  1303. if (err.Succeeded())
  1304. {
  1305. //
  1306. // Read off the open key
  1307. //
  1308. err = mk.QueryValue(
  1309. MD_SERVER_COMMENT,
  1310. strComment,
  1311. NULL,
  1312. strTemplate
  1313. );
  1314. if (err.Succeeded())
  1315. {
  1316. TRACEEOLID(strComment);
  1317. //
  1318. // Append the comment in the off-screen
  1319. // area of the listbox
  1320. //
  1321. strListItem.Format(_T("%s\t%s"),
  1322. (LPCTSTR)strTemplate,
  1323. (LPCTSTR)strComment
  1324. );
  1325. m_list_Templates.AddString(strListItem);
  1326. }
  1327. }
  1328. }
  1329. }
  1330. while(FALSE);
  1331. if (err.Failed())
  1332. {
  1333. if (err.Win32Error() == ERROR_PATH_NOT_FOUND)
  1334. {
  1335. AfxMessageBox(IDS_NO_TEMPLATES);
  1336. }
  1337. else if (err.Win32Error() != ERROR_NO_MORE_ITEMS)
  1338. {
  1339. err.MessageBox();
  1340. }
  1341. }
  1342. return TRUE;
  1343. }
  1344. void
  1345. CPWTemplate::OnSelchangeListTemplates()
  1346. /*++
  1347. Routine Description:
  1348. Handle selection change in the templates listbox
  1349. Arguments:
  1350. None
  1351. Return Value:
  1352. None
  1353. --*/
  1354. {
  1355. int nSel = m_list_Templates.GetCurSel();
  1356. ASSERT(nSel >= 0);
  1357. if (nSel >= 0)
  1358. {
  1359. CString strItem;
  1360. m_list_Templates.GetText(nSel, strItem);
  1361. //
  1362. // Fetch the comment, which is just beyond the tab
  1363. // character
  1364. //
  1365. int nTab = strItem.Find(_T('\t'));
  1366. ASSERT(nTab >= 0);
  1367. if (nTab >= 0)
  1368. {
  1369. strItem = strItem.Mid(nTab + 1);
  1370. }
  1371. m_edit_Description.SetWindowText(_T(""));
  1372. m_edit_Description.SetWindowText(strItem);
  1373. Invalidate();
  1374. UpdateWindow();
  1375. }
  1376. SetControlStates();
  1377. }
  1378. //
  1379. // Permissions Wizard ACL Page
  1380. //
  1381. // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  1382. IMPLEMENT_DYNCREATE(CPWACL, CIISWizardPage)
  1383. CPWACL::CPWACL(
  1384. IN CIISSecWizSettings * pSettings
  1385. )
  1386. /*++
  1387. Routine Description:
  1388. Constructor
  1389. Arguments:
  1390. CIISSecWizSettings * pSettings : Settings
  1391. Return Value:
  1392. None
  1393. --*/
  1394. : CIISWizardPage(
  1395. CPWACL::IDD, // Template
  1396. IDS_PERMWIZ, // Caption,
  1397. HEADER_PAGE // Header
  1398. ),
  1399. m_pSettings(pSettings)
  1400. {
  1401. //{{AFX_DATA_INIT(CPWACL)
  1402. m_nRadioAclType = RADIO_MAXIMUM;
  1403. //}}AFX_DATA_INIT
  1404. ASSERT(m_pSettings);
  1405. // ASSERT(!m_pSettings->m_strServer.IsEmpty());
  1406. }
  1407. CPWACL::~CPWACL()
  1408. /*++
  1409. Routine Description:
  1410. Destructor
  1411. Arguments:
  1412. N/A
  1413. Return Value:
  1414. N/A
  1415. --*/
  1416. {
  1417. }
  1418. void
  1419. CPWACL::DoDataExchange(
  1420. IN CDataExchange * pDX
  1421. )
  1422. /*++
  1423. Routine Description:
  1424. Initialise/Store control data
  1425. Arguments:
  1426. CDataExchange * pDX - DDX/DDV control structure
  1427. Return Value:
  1428. None
  1429. --*/
  1430. {
  1431. CIISWizardPage::DoDataExchange(pDX);
  1432. //{{AFX_DATA_MAP(CPWACL)
  1433. DDX_Control(pDX, IDC_ED_BOLD4, m_static_Line4);
  1434. DDX_Control(pDX, IDC_ED_BOLD3, m_static_Line3);
  1435. DDX_Control(pDX, IDC_ED_BOLD2, m_static_Line2);
  1436. DDX_Control(pDX, IDC_ED_BOLD1, m_static_Line1);
  1437. DDX_Radio(pDX, IDC_RADIO_ACL_MAXIMUM, m_nRadioAclType);
  1438. //}}AFX_DATA_MAP
  1439. }
  1440. void
  1441. CPWACL::SetControlStates()
  1442. /*++
  1443. Routine Description:
  1444. Set the state of the control data
  1445. Arguments:
  1446. None
  1447. Return Value:
  1448. None
  1449. --*/
  1450. {
  1451. SetWizardButtons(PSWIZB_NEXT | PSWIZB_BACK);
  1452. }
  1453. //
  1454. // Message Map
  1455. //
  1456. BEGIN_MESSAGE_MAP(CPWACL, CIISWizardPage)
  1457. //{{AFX_MSG_MAP(CPWACL)
  1458. //}}AFX_MSG_MAP
  1459. END_MESSAGE_MAP()
  1460. BOOL
  1461. GetPhysicalPath(
  1462. IN CMetaKey & mk,
  1463. IN CString & strMetaPath,
  1464. OUT CString & strPhysicalPath
  1465. )
  1466. /*++
  1467. Routine Description:
  1468. Get the physical path of the parent as described by the metabase path
  1469. Arguments:
  1470. CMetaKey & mk : Open metabase key
  1471. CString & strMetaPath : Metabase path
  1472. CString & strPhysicalPath : Returns physical path
  1473. Return Value:
  1474. TRUE for success, FALSE for failure
  1475. --*/
  1476. {
  1477. //
  1478. // Get physical path of parent
  1479. //
  1480. CString strAlias;
  1481. int nSlash = strMetaPath.ReverseFind(SZ_MBN_SEP_CHAR);
  1482. if (nSlash < 0)
  1483. {
  1484. //
  1485. // Didn't encounter a physical path at all!
  1486. //
  1487. TRACEEOLID("No physical path established -- ACLS skipped");
  1488. ASSERT(FALSE);
  1489. return FALSE;
  1490. }
  1491. strAlias = strMetaPath.Mid(nSlash + 1);
  1492. strMetaPath.ReleaseBuffer(nSlash);
  1493. TRACEEOLID(strAlias);
  1494. TRACEEOLID(strMetaPath);
  1495. BOOL fInherit = FALSE;
  1496. CError err(mk.QueryValue(
  1497. MD_VR_PATH,
  1498. strPhysicalPath,
  1499. &fInherit,
  1500. strMetaPath
  1501. ));
  1502. if (err.Failed())
  1503. {
  1504. GetPhysicalPath(mk, strMetaPath, strPhysicalPath);
  1505. }
  1506. strPhysicalPath += _T("\\");
  1507. strPhysicalPath += strAlias;
  1508. return TRUE;
  1509. }
  1510. //
  1511. // Message Handlers
  1512. //
  1513. // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  1514. LRESULT
  1515. CPWACL::OnWizardNext()
  1516. /*++
  1517. Routine Description:
  1518. 'next' handler. Store the acl replacement type specified, so the next
  1519. pages can skip or continue.
  1520. Arguments:
  1521. None
  1522. Return Value:
  1523. 0 to proceed, -1 to fail
  1524. --*/
  1525. {
  1526. UpdateData(TRUE);
  1527. switch(m_nRadioAclType)
  1528. {
  1529. case RADIO_MINIMUM:
  1530. m_pSettings->m_fReplaceAcls = FALSE;
  1531. break;
  1532. case RADIO_MAXIMUM:
  1533. m_pSettings->m_fReplaceAcls = TRUE;
  1534. break;
  1535. case RADIO_NONE:
  1536. default:
  1537. m_pSettings->m_fSetAcls = FALSE;
  1538. }
  1539. return CIISWizardPage::OnWizardNext();
  1540. }
  1541. static PSID psidAdministrators = NULL;
  1542. static PSID psidEveryone = NULL;
  1543. BOOL
  1544. CPWACL::OnSetActive()
  1545. /*++
  1546. Routine Description:
  1547. Activation handler
  1548. Arguments:
  1549. None
  1550. Return Value:
  1551. TRUE to show the page, FALSE to skip it.
  1552. --*/
  1553. {
  1554. //
  1555. // Assume no acls until all tests pass
  1556. //
  1557. m_pSettings->m_fSetAcls = FALSE;
  1558. if (!m_pSettings->m_auth->IsLocal())
  1559. {
  1560. TRACEEOLID("We're not local -- skipping ACL phase");
  1561. return FALSE;
  1562. }
  1563. //
  1564. // Get properties on the current directory object
  1565. //
  1566. CChildNodeProps props(
  1567. m_pSettings->m_auth,
  1568. m_pSettings->m_strMDPath,
  1569. WITH_INHERITANCE
  1570. );
  1571. CError err(props.LoadData());
  1572. if (err.MessageBoxOnFailure())
  1573. {
  1574. TRACEEOLID("Unable to determine directory properties -- skipping ACLS");
  1575. ASSERT(FALSE);
  1576. return FALSE;
  1577. }
  1578. m_pSettings->m_fRedirected = props.IsRedirected();
  1579. if (m_pSettings->m_fRedirected)
  1580. {
  1581. TRACEEOLID("Redirection in place, will not set ACLS");
  1582. return FALSE;
  1583. }
  1584. //
  1585. // If the path is on a remote store, Then no ACL page. - boydm
  1586. //
  1587. if (::IsUNCName(MP_V(props.m_strPath)))
  1588. {
  1589. TRACEEOLID("share is remote, will not set ACLS");
  1590. return FALSE;
  1591. }
  1592. //
  1593. // Don't get confused here, build the real physical path
  1594. //
  1595. if (props.IsPathInherited())
  1596. {
  1597. TRACEEOLID("Path inherited");
  1598. //
  1599. // Look for parent path.
  1600. //
  1601. CString strMetaPath(props.QueryMetaRoot());
  1602. TRACEEOLID(strMetaPath);
  1603. CMetaKey mk(m_pSettings->m_auth);
  1604. err = mk.QueryResult();
  1605. if (err.Failed())
  1606. {
  1607. ASSERT(FALSE);
  1608. return FALSE;
  1609. }
  1610. if (!GetPhysicalPath(mk, strMetaPath, m_pSettings->m_strPath))
  1611. {
  1612. ASSERT(FALSE);
  1613. return FALSE;
  1614. }
  1615. }
  1616. else
  1617. {
  1618. m_pSettings->m_strPath = props.m_strPath;
  1619. }
  1620. DWORD dwFileSystemFlags;
  1621. if (::GetVolumeInformationSystemFlags(
  1622. m_pSettings->m_strPath,
  1623. &dwFileSystemFlags
  1624. ))
  1625. {
  1626. if (!(dwFileSystemFlags & FS_PERSISTENT_ACLS))
  1627. {
  1628. //
  1629. // No ACLS
  1630. //
  1631. TRACEEOLID("Volume type doesn't accept ACLS -- skipping");
  1632. return FALSE;
  1633. }
  1634. }
  1635. //
  1636. // Build ACL information to be set
  1637. //
  1638. m_pSettings->m_AccessMaskAdmin = ACCMASK_ADMIN_FLAGS;
  1639. m_pSettings->m_AccessMaskDefault
  1640. = m_pSettings->m_AccessMaskEveryone = ACC_MASK_EVERYONE_FLAGS;
  1641. //
  1642. // Display proposed ACEs in bold-faced entries on the dialog
  1643. //
  1644. UINT nID = IDC_ED_BOLD1;
  1645. CString str;
  1646. VERIFY(str.LoadString(IDS_ACL_ADMINS));
  1647. GetDlgItem(nID++)->SetWindowText(str);
  1648. if (IS_FLAG_SET(m_pSettings->m_pist->m_dwAccessPerms, MD_ACCESS_READ))
  1649. {
  1650. VERIFY(str.LoadString(IDS_ACL_EV_READ));
  1651. GetDlgItem(nID++)->SetWindowText(str);
  1652. m_pSettings->m_AccessMaskEveryone |= ACCMASK_READ_FLAGS;
  1653. }
  1654. if (IS_FLAG_SET(m_pSettings->m_pist->m_dwAccessPerms, MD_ACCESS_WRITE))
  1655. {
  1656. VERIFY(str.LoadString(IDS_ACL_EV_WRITE));
  1657. GetDlgItem(nID++)->SetWindowText(str);
  1658. m_pSettings->m_AccessMaskEveryone |= ACCMASK_WRITE_FLAGS;
  1659. }
  1660. if (IS_FLAG_SET(m_pSettings->m_pist->m_dwAccessPerms, MD_ACCESS_EXECUTE))
  1661. {
  1662. VERIFY(str.LoadString(IDS_ACL_EV_EXEC));
  1663. GetDlgItem(nID++)->SetWindowText(str);
  1664. m_pSettings->m_AccessMaskEveryone |= ACCMASK_EXEC_FLAGS;
  1665. }
  1666. ZeroMemory(&m_pSettings->m_rgaae, sizeof(m_pSettings->m_rgaae));
  1667. SID_IDENTIFIER_AUTHORITY siaNtAuthority = SECURITY_NT_AUTHORITY;
  1668. SID_IDENTIFIER_AUTHORITY siaWorldSidAuthority = SECURITY_WORLD_SID_AUTHORITY;
  1669. AllocateAndInitializeSid(
  1670. &siaNtAuthority,
  1671. 2,
  1672. SECURITY_BUILTIN_DOMAIN_RID,
  1673. DOMAIN_ALIAS_RID_ADMINS,
  1674. 0, 0, 0, 0, 0, 0,
  1675. &psidAdministrators);
  1676. AllocateAndInitializeSid(
  1677. &siaWorldSidAuthority,
  1678. 1,
  1679. SECURITY_WORLD_RID,
  1680. 0, 0, 0, 0, 0, 0, 0,
  1681. &psidEveryone);
  1682. //
  1683. // Set up permissions for the "Everyone" group
  1684. //
  1685. m_pSettings->m_rgaae[0].Trustee.pMultipleTrustee = NULL;
  1686. m_pSettings->m_rgaae[0].Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
  1687. m_pSettings->m_rgaae[0].Trustee.TrusteeForm = TRUSTEE_IS_SID;
  1688. m_pSettings->m_rgaae[0].Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
  1689. m_pSettings->m_rgaae[0].Trustee.ptstrName = (LPTSTR)psidEveryone;
  1690. m_pSettings->m_rgaae[0].grfAccessMode = SET_ACCESS;
  1691. m_pSettings->m_rgaae[0].grfAccessPermissions = m_pSettings->m_AccessMaskEveryone;
  1692. m_pSettings->m_rgaae[0].grfInheritance = SUB_CONTAINERS_AND_OBJECTS_INHERIT;
  1693. //
  1694. // Set up permissions for the "Administrators" group
  1695. //
  1696. m_pSettings->m_rgaae[1].Trustee.pMultipleTrustee = NULL;
  1697. m_pSettings->m_rgaae[1].Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
  1698. m_pSettings->m_rgaae[1].Trustee.TrusteeForm = TRUSTEE_IS_SID;
  1699. m_pSettings->m_rgaae[1].Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
  1700. m_pSettings->m_rgaae[1].Trustee.ptstrName = (LPTSTR)psidAdministrators;
  1701. m_pSettings->m_rgaae[1].grfAccessMode = SET_ACCESS;
  1702. m_pSettings->m_rgaae[1].grfAccessPermissions = m_pSettings->m_AccessMaskAdmin;
  1703. m_pSettings->m_rgaae[1].grfInheritance = SUB_CONTAINERS_AND_OBJECTS_INHERIT;
  1704. SetControlStates();
  1705. //
  1706. // Passed all tests, we'll give the option to set ACLS
  1707. //
  1708. m_pSettings->m_fSetAcls = TRUE;
  1709. return CIISWizardPage::OnSetActive();
  1710. }
  1711. //
  1712. // Permissions Wizard Template Page
  1713. //
  1714. // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  1715. IMPLEMENT_DYNCREATE(CPWSummary, CIISWizardPage)
  1716. CPWSummary::CPWSummary(
  1717. IN CIISSecWizSettings * pSettings
  1718. )
  1719. /*++
  1720. Routine Description:
  1721. Constructor
  1722. Arguments:
  1723. CIISSecWizSettings * pSettings : Settings
  1724. Return Value:
  1725. None
  1726. --*/
  1727. : CIISWizardPage(
  1728. CPWSummary::IDD, // Template
  1729. IDS_PERMWIZ, // Caption
  1730. HEADER_PAGE // Header
  1731. ),
  1732. m_pSettings(pSettings)
  1733. {
  1734. //{{AFX_DATA_INIT(CPWSummary)
  1735. //}}AFX_DATA_INIT
  1736. ASSERT(m_pSettings);
  1737. // ASSERT(!m_pSettings->m_strServer.IsEmpty());
  1738. }
  1739. CPWSummary::~CPWSummary()
  1740. /*++
  1741. Routine Description:
  1742. Destructor
  1743. Arguments:
  1744. N/A
  1745. Return Value:
  1746. N/A
  1747. --*/
  1748. {
  1749. }
  1750. void
  1751. CPWSummary::DoDataExchange(
  1752. IN CDataExchange * pDX
  1753. )
  1754. /*++
  1755. Routine Description:
  1756. Initialise/Store control data
  1757. Arguments:
  1758. CDataExchange * pDX - DDX/DDV control structure
  1759. Return Value:
  1760. None
  1761. --*/
  1762. {
  1763. CIISWizardPage::DoDataExchange(pDX);
  1764. //{{AFX_DATA_MAP(CPWSummary)
  1765. DDX_Control(pDX, IDC_LIST_SUMMARY, m_list_Summary);
  1766. //}}AFX_DATA_MAP
  1767. }
  1768. void
  1769. CPWSummary::SetControlStates()
  1770. /*++
  1771. Routine Description:
  1772. Set the state of the control data
  1773. Arguments:
  1774. None
  1775. Return Value:
  1776. None
  1777. --*/
  1778. {
  1779. SetWizardButtons(PSWIZB_NEXT | PSWIZB_BACK);
  1780. }
  1781. //
  1782. // Message Map
  1783. //
  1784. BEGIN_MESSAGE_MAP(CPWSummary, CIISWizardPage)
  1785. //{{AFX_MSG_MAP(CPWSummary)
  1786. //}}AFX_MSG_MAP
  1787. END_MESSAGE_MAP()
  1788. void
  1789. CPWSummary::GenerateAclSummary()
  1790. /*++
  1791. Routine Description:
  1792. Break down ACL list into the summary
  1793. Arguments:
  1794. None
  1795. Return Value:
  1796. None
  1797. --*/
  1798. {
  1799. //
  1800. // Summarize ACL Settings:
  1801. //
  1802. int nIndentLevel = 0;
  1803. if (m_pSettings->m_fSetAcls)
  1804. {
  1805. m_pSettings->m_pist->AddSummaryString(
  1806. m_pSettings->m_fReplaceAcls
  1807. ? IDS_ACL_REPLACEMENT
  1808. : IDS_ACL_ADDED,
  1809. nIndentLevel++
  1810. );
  1811. m_pSettings->m_pist->AddSummaryString(IDS_ACL_ADMIN, nIndentLevel);
  1812. m_pSettings->m_pist->AddSummaryString(IDS_ACL_EVR, nIndentLevel++);
  1813. // if (m_pSettings->m_AccessMaskEveryone
  1814. // == m_pSettings->m_AccessMaskDefault)
  1815. // {
  1816. // //
  1817. // // "Everyone" has zero access
  1818. // //
  1819. // m_pSettings->m_pist->AddSummaryString(
  1820. // IDS_SUMMARY_NONE,
  1821. // nIndentLevel
  1822. // );
  1823. // }
  1824. // else
  1825. // {
  1826. //
  1827. // Enumerate the specific rights granted
  1828. // to "everyone"
  1829. //
  1830. for (int i = 0; i < ARRAY_SIZE(fsAclFlags); ++i)
  1831. {
  1832. if (IS_FLAG_SET(
  1833. m_pSettings->m_AccessMaskEveryone,
  1834. fsAclFlags[i].dwFlag
  1835. ) == fsAclFlags[i].fSet)
  1836. {
  1837. m_pSettings->m_pist->AddSummaryString(
  1838. fsAclFlags[i].nID,
  1839. nIndentLevel
  1840. );
  1841. }
  1842. }
  1843. // }
  1844. }
  1845. else
  1846. {
  1847. m_pSettings->m_pist->AddSummaryString(IDS_ACL_NONE, nIndentLevel);
  1848. }
  1849. }
  1850. void
  1851. CPWSummary::DisplaySummary()
  1852. /*++
  1853. Routine Description:
  1854. Break down the security settings and display them in text
  1855. form in the summary listbox.
  1856. Arguments:
  1857. None
  1858. Return Value:
  1859. None.
  1860. --*/
  1861. {
  1862. //
  1863. // Generate Summary
  1864. //
  1865. m_pSettings->m_pist->ClearSummary();
  1866. m_pSettings->m_pist->GenerateSummary(
  1867. m_pSettings->m_fUseTemplate,
  1868. m_pSettings->m_auth,
  1869. m_pSettings->m_strMDPath
  1870. );
  1871. GenerateAclSummary();
  1872. //
  1873. // Display it in the listbox
  1874. //
  1875. m_list_Summary.ResetContent();
  1876. POSITION pos = m_pSettings->m_pist->GetHeadPosition();
  1877. while(pos)
  1878. {
  1879. CString & str = m_pSettings->m_pist->GetNext(pos);
  1880. m_list_Summary.AddString(str);
  1881. }
  1882. }
  1883. //
  1884. // Message Handlers
  1885. //
  1886. // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  1887. BOOL
  1888. CPWSummary::OnSetActive()
  1889. {
  1890. SetControlStates();
  1891. DisplaySummary();
  1892. return CIISWizardPage::OnSetActive();
  1893. }
  1894. /* virtual */
  1895. LRESULT
  1896. CPWSummary::OnWizardNext()
  1897. {
  1898. //
  1899. // Store everything here
  1900. //
  1901. CError err(m_pSettings->m_pist->ApplySettings(
  1902. m_pSettings->m_fUseTemplate,
  1903. m_pSettings->m_auth,
  1904. m_pSettings->m_strMDPath
  1905. ));
  1906. //
  1907. // Set the ACLS
  1908. //
  1909. if (err.Succeeded() && m_pSettings->m_fSetAcls)
  1910. {
  1911. err = ApplyACLSToFiles();
  1912. }
  1913. //
  1914. // Store the error for the completion page
  1915. //
  1916. m_pSettings->m_hResult = err;
  1917. return CIISWizardPage::OnWizardNext();
  1918. }
  1919. HRESULT
  1920. CPWSummary::ApplyACLSToFiles()
  1921. /*++
  1922. Routine Description:
  1923. Apply ACLS to files
  1924. Arguments:
  1925. None
  1926. Return Value:
  1927. HRESULT
  1928. --*/
  1929. {
  1930. CError err;
  1931. SECURITY_INFORMATION si = 0;
  1932. SECURITY_DESCRIPTOR * psd = NULL;
  1933. PACL pOldDacl = NULL, pNewDacl = NULL;;
  1934. //
  1935. // Can take a while.
  1936. //
  1937. CWaitCursor waitcursor;
  1938. do
  1939. {
  1940. err = GetNamedSecurityInfo(
  1941. (LPTSTR)(LPCTSTR)m_pSettings->m_strPath,
  1942. SE_FILE_OBJECT,
  1943. DACL_SECURITY_INFORMATION,
  1944. NULL, // owner SID
  1945. NULL, // group SID
  1946. &pOldDacl, // pointer to the DACL
  1947. NULL, // pointer to the SACL
  1948. (PVOID *)&psd
  1949. );
  1950. BREAK_ON_ERR_FAILURE(err);
  1951. if (!m_pSettings->m_fReplaceAcls)
  1952. {
  1953. m_pSettings->m_rgaae[0].grfAccessMode = GRANT_ACCESS;
  1954. m_pSettings->m_rgaae[1].grfAccessMode = GRANT_ACCESS;
  1955. }
  1956. // Prepare DACL according to template
  1957. err = SetEntriesInAcl(
  1958. ARRAY_SIZE(m_pSettings->m_rgaae),
  1959. m_pSettings->m_rgaae,
  1960. m_pSettings->m_fReplaceAcls ? NULL : pOldDacl,
  1961. &pNewDacl
  1962. );
  1963. BREAK_ON_ERR_FAILURE(err);
  1964. // Set permissions on the selected object
  1965. si |= DACL_SECURITY_INFORMATION;
  1966. si |= PROTECTED_DACL_SECURITY_INFORMATION;
  1967. err = HRESULT_FROM_WIN32(SetNamedSecurityInfo(
  1968. (LPTSTR)(LPCTSTR)m_pSettings->m_strPath,
  1969. SE_FILE_OBJECT,
  1970. si,
  1971. NULL,
  1972. NULL,
  1973. pNewDacl,
  1974. NULL));
  1975. BREAK_ON_ERR_FAILURE(err);
  1976. // For children of this object we should set empty DACL
  1977. // if we need only permissions inherited from parent
  1978. if (PathIsDirectory(m_pSettings->m_strPath))
  1979. {
  1980. if (m_pSettings->m_fReplaceAcls)
  1981. {
  1982. // Build security descriptor with empty DACL
  1983. ACL daclEmpty = {0};
  1984. InitializeAcl(&daclEmpty, sizeof(ACL), ACL_REVISION);
  1985. si = 0;
  1986. si |= DACL_SECURITY_INFORMATION;
  1987. si |= UNPROTECTED_DACL_SECURITY_INFORMATION;
  1988. err = SetPermToChildren(
  1989. m_pSettings->m_strPath,
  1990. si,
  1991. &daclEmpty,
  1992. NULL);
  1993. BREAK_ON_ERR_FAILURE(err);
  1994. }
  1995. }
  1996. // In other cases children should inherit permissions from the parent
  1997. }
  1998. while(FALSE);
  1999. if (pOldDacl != NULL)
  2000. {
  2001. LocalFree(pOldDacl);
  2002. }
  2003. if (pNewDacl != NULL)
  2004. {
  2005. LocalFree(pNewDacl);
  2006. }
  2007. if (psd != NULL)
  2008. {
  2009. LocalFree(psd);
  2010. }
  2011. return err;
  2012. }
  2013. BOOL
  2014. CPWSummary::OnInitDialog()
  2015. /*++
  2016. Routine Description:
  2017. WM_INITDIALOG handler. Initialize the dialog.
  2018. Arguments:
  2019. None.
  2020. Return Value:
  2021. TRUE if no focus is to be set automatically, FALSE if the focus
  2022. is already set.
  2023. --*/
  2024. {
  2025. CIISWizardPage::OnInitDialog();
  2026. //
  2027. // Set the tabs based on the hidden column headers
  2028. //
  2029. CRect rc1, rc2;
  2030. ASSERT(NULL != GetDlgItem(IDC_STATIC_TAB2) && NULL != GetDlgItem(IDC_STATIC_TAB1));
  2031. if (NULL != GetDlgItem(IDC_STATIC_TAB2) && NULL != GetDlgItem(IDC_STATIC_TAB1))
  2032. {
  2033. GetDlgItem(IDC_STATIC_TAB2)->GetWindowRect(&rc2);
  2034. GetDlgItem(IDC_STATIC_TAB1)->GetWindowRect(&rc1);
  2035. m_list_Summary.SetTabStops(((LPRECT)rc2)->left - ((LPRECT)rc1)->left);
  2036. }
  2037. return TRUE;
  2038. }
  2039. HRESULT
  2040. RunSecurityWizard(
  2041. CComAuthInfo * pauth,
  2042. CMetaInterface * pInterface,
  2043. CString& meta_path,
  2044. UINT nLeftBmpId,
  2045. UINT nHeadBmpId
  2046. )
  2047. {
  2048. CError err;
  2049. ASSERT(pInterface != NULL);
  2050. BOOL fAdmin;
  2051. err = DetermineIfAdministrator(
  2052. pInterface, meta_path, &fAdmin);
  2053. if (err.Failed() || !fAdmin)
  2054. {
  2055. AfxMessageBox(IDS_ACL_ADMINS);
  2056. return err;
  2057. }
  2058. CIISWizardSheet sheet(nLeftBmpId, nHeadBmpId);
  2059. CIISSecWizSettings sws(pauth, meta_path);
  2060. CIISWizardBookEnd pgWelcome(IDS_PWIZ_WELCOME, IDS_PERMWIZ, IDS_PWIZ_BODY);
  2061. CPWSource pgSource(&sws);
  2062. CPWTemplate pgTemplate(&sws);
  2063. CPWACL pgACL(&sws);
  2064. CPWSummary pgSummary(&sws);
  2065. CIISWizardBookEnd pgCompletion(&sws.m_hResult,
  2066. IDS_PWIZ_SUCCESS, IDS_PWIZ_FAILURE, IDS_PERMWIZ);
  2067. sheet.AddPage(&pgWelcome);
  2068. sheet.AddPage(&pgSource);
  2069. sheet.AddPage(&pgTemplate);
  2070. sheet.AddPage(&pgACL);
  2071. sheet.AddPage(&pgSummary);
  2072. sheet.AddPage(&pgCompletion);
  2073. sheet.DoModal();
  2074. return err;
  2075. }
  2076. BOOL CheckIfParentHasAccess(CComAuthInfo *pAuthInfo, CString csMetabaseNode)
  2077. {
  2078. int iReturn = TRUE;
  2079. CError err;
  2080. // check if the node is "/LM/W3SVC/1/Root"
  2081. if (TRUE == ConvertToServiceLevelPath(csMetabaseNode))
  2082. {
  2083. // look at this /lm/w3svc node to see if there is access
  2084. // at this node.
  2085. CMetaKey mk1(pAuthInfo,csMetabaseNode);
  2086. err = mk1.QueryResult();
  2087. if (err.Failed())
  2088. {
  2089. // let it inherit by default
  2090. iReturn = TRUE;
  2091. goto CheckIfParentHasAccess_Exit;
  2092. }
  2093. DWORD dwAccessPerms;
  2094. err = mk1.QueryValue(MD_ACCESS_PERM, dwAccessPerms);
  2095. if (err.Succeeded())
  2096. {
  2097. iReturn = TRUE;
  2098. }
  2099. else
  2100. {
  2101. iReturn = FALSE;
  2102. }
  2103. mk1.Close();
  2104. }
  2105. CheckIfParentHasAccess_Exit:
  2106. return iReturn;
  2107. }
  2108. BOOL ConvertToServiceLevelPath(CString &strMetaPath)
  2109. /*++
  2110. Routine Description:
  2111. Given the path, convert it to the service level path
  2112. e.g. "/LM/W3SVC/1/ROOT" returns "/LM/W3SVC/"
  2113. Arguments:
  2114. CString & strMetaPath : Path to be converted
  2115. Return value:
  2116. Pointer to the converted path, or NULL in case of error
  2117. --*/
  2118. {
  2119. // TRIM Off the last "/" or "\"
  2120. INT iLen = 0;
  2121. BOOL iReturn= 0;
  2122. LPTSTR lpBuffer = NULL;
  2123. LPTSTR pch1 = NULL;
  2124. LPTSTR pch2 = NULL;
  2125. iLen = strMetaPath.GetLength();
  2126. lpBuffer = (LPTSTR) LocalAlloc(LMEM_FIXED, (iLen + 1) * sizeof(TCHAR));
  2127. if (!lpBuffer)
  2128. {
  2129. return FALSE;
  2130. }
  2131. _tcscpy(lpBuffer,strMetaPath);
  2132. pch1 = _tcsrchr(lpBuffer, _T('/'));
  2133. if(pch1)
  2134. {
  2135. *pch1 = _T('\0');
  2136. }
  2137. else
  2138. {
  2139. pch1 = _tcsrchr(pch1, _T('\\'));
  2140. if(pch1){*pch1 = _T('\0');}
  2141. }
  2142. pch2 = _tcsrchr(lpBuffer, _T('/'));
  2143. if(pch2){*pch2 = _T('\0');}
  2144. else
  2145. {
  2146. pch2 = _tcsrchr(lpBuffer, _T('\\'));
  2147. if(pch2){*pch2 = _T('\0');}
  2148. }
  2149. strMetaPath = lpBuffer;
  2150. if (lpBuffer){LocalFree(lpBuffer);}
  2151. return TRUE;
  2152. }