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.

2379 lines
44 KiB

  1. /*++
  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 "comprop.h"
  18. #include <aclapi.h>
  19. #include <ntseapi.h>
  20. #include <shlwapi.h>
  21. //
  22. // IIS Security Template Class
  23. //
  24. // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  25. //
  26. // Package of access rights granted for "READ" access
  27. //
  28. #define ACCMASK_READ_FLAGS (0L\
  29. | FILE_READ_DATA\
  30. | READ_CONTROL\
  31. | SYNCHRONIZE\
  32. | FILE_READ_ATTRIBUTES\
  33. | FILE_READ_EA\
  34. )
  35. //
  36. // Package of access rights granted for "WRITE" access
  37. //
  38. // Note: This includes "delete" because the web service assumes
  39. // "delete" when granting write access. This differs from
  40. // the norm.
  41. //
  42. #define ACCMASK_WRITE_FLAGS (0L\
  43. | FILE_WRITE_DATA\
  44. | FILE_APPEND_DATA\
  45. | DELETE\
  46. | FILE_WRITE_ATTRIBUTES\
  47. | FILE_WRITE_EA\
  48. )
  49. //
  50. // Package of access rights granted for "EXECUTE" access
  51. //
  52. #define ACCMASK_EXEC_FLAGS (0L\
  53. | FILE_EXECUTE\
  54. )
  55. //
  56. // Package of access rights granted for "DIR BROWSE" access
  57. //
  58. //#define ACCMASK_DIRBROWSE_FLAGS (0L\
  59. // | DS_LIST_OBJECT\
  60. // )
  61. //
  62. // Package of access rights granted for "FULL CONTROL" access
  63. //
  64. #define ACCMASK_ADMIN_FLAGS (0L\
  65. | STANDARD_RIGHTS_ALL\
  66. | FILE_READ_DATA\
  67. | FILE_WRITE_DATA\
  68. | FILE_APPEND_DATA\
  69. | FILE_READ_EA\
  70. | FILE_WRITE_EA\
  71. | FILE_EXECUTE\
  72. | FILE_ADD_FILE\
  73. | FILE_ADD_SUBDIRECTORY\
  74. | FILE_READ_ATTRIBUTES\
  75. | FILE_WRITE_ATTRIBUTES\
  76. | FILE_LIST_DIRECTORY\
  77. | FILE_DELETE_CHILD\
  78. | FILE_TRAVERSE\
  79. | ACTRL_DS_LIST_OBJECT\
  80. )
  81. //
  82. // Package of access rights granted for "Everyone"
  83. #define ACC_MASK_EVERYONE_FLAGS (0L\
  84. | ACCMASK_READ_FLAGS\
  85. | ACCMASK_EXEC_FLAGS\
  86. )
  87. //
  88. //
  89. // Access permission bit strings
  90. //
  91. FLAGTOSTRING fsAccessPerms[] =
  92. {
  93. { MD_ACCESS_READ, IDS_PERMS_READ, TRUE },
  94. { MD_ACCESS_WRITE, IDS_PERMS_WRITE, TRUE },
  95. { MD_ACCESS_SCRIPT, IDS_PERMS_SCRIPT, TRUE },
  96. { MD_ACCESS_EXECUTE, IDS_PERMS_EXECUTE, TRUE },
  97. };
  98. //
  99. // Access mask bit strings
  100. //
  101. FLAGTOSTRING fsAclFlags[] =
  102. {
  103. { FILE_READ_DATA, IDS_ACL_READ, TRUE },
  104. { READ_CONTROL, IDS_ACL_READ_CONTROL, TRUE },
  105. { FILE_READ_ATTRIBUTES, IDS_ACL_READ_ATTRIB, TRUE },
  106. { FILE_READ_EA, IDS_ACL_READ_PROP, TRUE },
  107. { FILE_WRITE_DATA, IDS_ACL_WRITE, TRUE },
  108. { FILE_APPEND_DATA, IDS_ACL_APPEND, TRUE },
  109. { DELETE, IDS_ACL_DELETE, TRUE },
  110. { FILE_WRITE_ATTRIBUTES, IDS_ACL_WRITE_ATTRIB, TRUE },
  111. { FILE_WRITE_EA, IDS_ACL_WRITE_PROP, TRUE },
  112. { FILE_EXECUTE, IDS_ACL_EXECUTE, TRUE },
  113. // { DS_LIST_CONTENTS, IDS_ACL_LIST_OBJECT, TRUE },
  114. };
  115. CIISSecurityTemplate::CIISSecurityTemplate(
  116. IN const CMetaKey * pKey,
  117. IN LPCTSTR lpszMDPath,
  118. IN BOOL fInherit
  119. )
  120. /*++
  121. Routine Description:
  122. Construct from open key
  123. Arguments:
  124. const CMetaKey * pKey : Open key
  125. LPCTSTR lpszMDPath : Path
  126. BOOL fInherit : TRUE to inherit properties
  127. Return Value:
  128. N/A
  129. --*/
  130. : CMetaProperties(pKey, lpszMDPath),
  131. m_dwAccessPerms(0L),
  132. m_dlProperties(),
  133. m_strlSummary(),
  134. m_ipl()
  135. {
  136. //
  137. // Set base class member
  138. //
  139. m_fInherit = fInherit;
  140. //
  141. // Managed Properties
  142. //
  143. m_dlProperties.AddTail(MD_ACCESS_PERM);
  144. m_dlProperties.AddTail(MD_IP_SEC);
  145. }
  146. /* virtual */
  147. void
  148. CIISSecurityTemplate::ParseFields()
  149. /*++
  150. Routine Description:
  151. Break into fields.
  152. Arguments:
  153. None.
  154. Return Value:
  155. None.
  156. --*/
  157. {
  158. BEGIN_PARSE_META_RECORDS(m_dwNumEntries, m_pbMDData)
  159. HANDLE_META_RECORD(MD_ACCESS_PERM, m_dwAccessPerms)
  160. HANDLE_META_RECORD(MD_IP_SEC, m_ipl)
  161. END_PARSE_META_RECORDS
  162. //
  163. // If "execute" or "script" is on, read should be as well (makes
  164. // little sense otherwise)
  165. //
  166. if (IS_FLAG_SET(
  167. MP_V(m_dwAccessPerms),
  168. (MD_ACCESS_EXECUTE | MD_ACCESS_SCRIPT)
  169. ))
  170. {
  171. SET_FLAG(MP_V(m_dwAccessPerms), MD_ACCESS_READ);
  172. }
  173. }
  174. /* virtual */
  175. HRESULT
  176. CIISSecurityTemplate::ApplySettings(
  177. IN BOOL fUseTemplate,
  178. IN LPCTSTR lpszServerName,
  179. IN LPCTSTR lpszService,
  180. IN DWORD dwInstance,
  181. IN LPCTSTR lpszParent,
  182. IN LPCTSTR lpszAlias
  183. )
  184. /*++
  185. Routine Description:
  186. Apply the settings to the specified destination path
  187. Arguments:
  188. BOOL fUseTemplates : TRUE if the source is from a template,
  189. FALSE if using inheritance.
  190. LPCTSTR lpszServerName : Server name
  191. LPCTSTR lpszService : Service name
  192. DWORD dwInstance : Instance
  193. LPCTSTR lpszParent : Parent path (or NULL)
  194. LPCTSTR lpszAlias : Alias name (or NULL)
  195. Return Value:
  196. HRESULT
  197. --*/
  198. {
  199. BOOL fWriteProperties = TRUE;
  200. CMetaKey mk(
  201. lpszServerName,
  202. METADATA_PERMISSION_WRITE,
  203. lpszService,
  204. dwInstance,
  205. lpszParent,
  206. lpszAlias
  207. );
  208. CError err(mk.QueryResult());
  209. if (err.Win32Error() == ERROR_PATH_NOT_FOUND)
  210. {
  211. if (fUseTemplate)
  212. {
  213. //
  214. // Create the path
  215. //
  216. err = mk.CreatePathFromFailedOpen();
  217. if (err.Succeeded())
  218. {
  219. err = mk.ReOpen(METADATA_PERMISSION_WRITE);
  220. }
  221. }
  222. else
  223. {
  224. //
  225. // No need to delete properties; everything's already
  226. // inherited.
  227. //
  228. fWriteProperties = FALSE;
  229. err.Reset();
  230. }
  231. }
  232. if (fWriteProperties)
  233. {
  234. do
  235. {
  236. BREAK_ON_ERR_FAILURE(err);
  237. if (fUseTemplate)
  238. {
  239. //
  240. // Write values from template
  241. //
  242. err = mk.SetValue(
  243. MD_ACCESS_PERM,
  244. m_dwAccessPerms
  245. );
  246. BREAK_ON_ERR_FAILURE(err);
  247. err = mk.SetValue(MD_IP_SEC, m_ipl);
  248. BREAK_ON_ERR_FAILURE(err);
  249. }
  250. else
  251. {
  252. //
  253. // We're going to use inheritance, so delete
  254. // the values that might exist here
  255. //
  256. ASSERT(m_dlProperties.GetCount() > 0);
  257. POSITION pos = m_dlProperties.GetHeadPosition();
  258. while(pos)
  259. {
  260. DWORD dwID = m_dlProperties.GetNext(pos);
  261. err = mk.DeleteValue(dwID);
  262. if (err.HResult() == MD_ERROR_DATA_NOT_FOUND)
  263. {
  264. //
  265. // That's ok
  266. //
  267. err.Reset();
  268. }
  269. if (err.Failed())
  270. {
  271. break;
  272. }
  273. }
  274. }
  275. }
  276. while(FALSE);
  277. }
  278. return err;
  279. }
  280. void
  281. CIISSecurityTemplate::AddSummaryString(
  282. IN LPCTSTR szTextItem,
  283. IN int cIndentLevel OPTIONAL
  284. )
  285. /*++
  286. Routine Description:
  287. Helper function to add strings to the summary
  288. Arguments:
  289. LPCTSTR szTextItem : String to be added
  290. int cIndentLevel : Indentation level
  291. Return Value:
  292. None
  293. --*/
  294. {
  295. CString str(szTextItem);
  296. //
  297. // Add a tab at the beginning of each string for each
  298. // level of indentation requested
  299. //
  300. for (int i = 0; i < cIndentLevel; ++i)
  301. {
  302. str = _T("\t") + str;
  303. }
  304. m_strlSummary.AddTail(str);
  305. }
  306. void
  307. CIISSecurityTemplate::AddSummaryString(
  308. IN UINT nID,
  309. IN int cIndentLevel OPTIONAL
  310. )
  311. /*++
  312. Routine Description:
  313. Helper function to add strings to the summary which are referred to
  314. by string table resource ID
  315. Arguments:
  316. UINT nID : Resource ID
  317. int cIndentLevel : Indentation level
  318. Return Value:
  319. None
  320. --*/
  321. {
  322. CString str;
  323. VERIFY(str.LoadString(nID));
  324. AddSummaryString(str, cIndentLevel);
  325. }
  326. /* virtual */
  327. void
  328. CIISSecurityTemplate::GenerateSummary(
  329. IN BOOL fUseTemplate,
  330. IN LPCTSTR lpszServerName,
  331. IN LPCTSTR lpszService,
  332. IN DWORD dwInstance,
  333. IN LPCTSTR lpszParent,
  334. IN LPCTSTR lpszAlias
  335. )
  336. /*++
  337. Routine Description:
  338. Generate text summary of what's in the security template
  339. Arguments:
  340. BOOL fUseTemplates : TRUE if the source is from a template,
  341. FALSE if using inheritance.
  342. LPCTSTR lpszServerName : Server name
  343. LPCTSTR lpszService : Service name
  344. DWORD dwInstance : Instance
  345. LPCTSTR lpszParent : Parent path (or NULL)
  346. LPCTSTR lpszAlias : Alias name (or NULL)
  347. Return Value:
  348. None
  349. Notes:
  350. This doesn't clear the summary. It's the responsibility of
  351. the calling process to clear beforehand, otherwise the summary
  352. items get added at the end.
  353. The derived class is expected to add its own information
  354. --*/
  355. {
  356. //
  357. // Summarize Access Permissions:
  358. //
  359. int nIndentLevel = 0;
  360. AddSummaryString(IDS_PERMISSIONS, nIndentLevel++);
  361. if (m_dwAccessPerms == 0L)
  362. {
  363. AddSummaryString(IDS_SUMMARY_NONE, nIndentLevel);
  364. }
  365. else
  366. {
  367. for (int i = 0; i < ARRAY_SIZE(fsAccessPerms); ++i)
  368. {
  369. if (IS_FLAG_SET(
  370. m_dwAccessPerms,
  371. fsAccessPerms[i].dwFlag
  372. ) == fsAccessPerms[i].fSet)
  373. {
  374. AddSummaryString(fsAccessPerms[i].nID, nIndentLevel);
  375. }
  376. }
  377. }
  378. //
  379. // Summarize IP Access Restrictions:
  380. //
  381. --nIndentLevel;
  382. AddSummaryString(IDS_ADDRESS_RESTRICTIONS, nIndentLevel++);
  383. if (MP_V(m_ipl).IsEmpty())
  384. {
  385. AddSummaryString(IDS_SUMMARY_NONE, nIndentLevel);
  386. }
  387. else
  388. {
  389. CObListPlus oblAccessList;
  390. BOOL fGrantByDefault;
  391. //
  392. // Get text version of ip access list for the summary
  393. //
  394. CError err(BuildIplOblistFromBlob(
  395. m_ipl,
  396. oblAccessList,
  397. fGrantByDefault
  398. ));
  399. if (err.Succeeded())
  400. {
  401. //
  402. // List default denied/granted state
  403. //
  404. AddSummaryString(
  405. fGrantByDefault ? IDS_SUMMARY_GRANTED : IDS_SUMMARY_DENIED,
  406. nIndentLevel
  407. );
  408. //
  409. // Enumerate restrictions (exceptions to the default)
  410. //
  411. CObListIter obli(oblAccessList);
  412. CIPAccessDescriptor * pAccess;
  413. CString str,
  414. strAddress,
  415. strGrpFormat,
  416. strGrantedFmt,
  417. strDeniedFmt;
  418. VERIFY(strGrantedFmt.LoadString(IDS_SPECIFIC_GRANTED));
  419. VERIFY(strDeniedFmt.LoadString(IDS_SPECIFIC_DENIED));
  420. VERIFY(strGrpFormat.LoadString(IDS_FMT_SECURITY));
  421. while (pAccess = (CIPAccessDescriptor *)obli.Next())
  422. {
  423. if (pAccess->IsDomainName())
  424. {
  425. strAddress = pAccess->QueryDomainName();
  426. }
  427. else if (pAccess->IsSingle())
  428. {
  429. strAddress = (LPCTSTR)pAccess->QueryIPAddress();
  430. }
  431. else
  432. {
  433. CString strIP, strMask;
  434. strAddress.Format(
  435. strGrpFormat,
  436. (LPCTSTR)pAccess->QueryIPAddress().QueryIPAddress(strIP),
  437. (LPCTSTR)pAccess->QuerySubnetMask().QueryIPAddress(strMask)
  438. );
  439. }
  440. str.Format(
  441. pAccess->HasAccess() ? strGrantedFmt : strDeniedFmt,
  442. strAddress
  443. );
  444. AddSummaryString(str, nIndentLevel);
  445. }
  446. }
  447. else
  448. {
  449. //
  450. // better than nothing
  451. //
  452. AddSummaryString(IDS_ADDRESS_IP, nIndentLevel);
  453. }
  454. }
  455. }
  456. CIISSecWizSettings::CIISSecWizSettings(
  457. IN pfnNewSecurityTemplate pfnTemplateAllocator,
  458. IN LPCTSTR lpszServer,
  459. IN LPCTSTR lpszService,
  460. IN DWORD dwInstance,
  461. IN LPCTSTR lpszParent,
  462. IN LPCTSTR lpszAlias
  463. )
  464. /*++
  465. Routine Description:
  466. Constructor
  467. Arguments:
  468. pfnNewSecurityTemplate pfnTemplateAllocator : Function to allocate templ.
  469. LPCTSTR lpszServer : Server name
  470. LPCTSTR lpszService : Service name
  471. DWORD dwInstance : Instance number
  472. LPCTSTR lpszParent : Parent path
  473. LPCTSTR lpszAlias : Alias node name
  474. Return Value:
  475. N/A
  476. --*/
  477. : CObjectPlus(),
  478. m_pfnTemplateAllocator(pfnTemplateAllocator),
  479. m_strServer(lpszServer),
  480. m_strService(lpszService),
  481. m_strParent(),
  482. m_strAlias(),
  483. m_dwInstance(dwInstance),
  484. m_fUseTemplate(TRUE),
  485. m_fSetAcls(FALSE),
  486. m_fReplaceAcls(FALSE),
  487. m_pist(NULL),
  488. m_hResult(S_OK)
  489. {
  490. if (lpszParent)
  491. {
  492. m_strParent = lpszParent;
  493. }
  494. if (lpszAlias)
  495. {
  496. m_strAlias = lpszAlias;
  497. }
  498. }
  499. CIISSecWizSettings::~CIISSecWizSettings()
  500. /*++
  501. Routine Description:
  502. Destructor
  503. Arguments:
  504. N/A
  505. Return Value:
  506. N/A
  507. --*/
  508. {
  509. if (m_pist != NULL)
  510. {
  511. delete m_pist;
  512. }
  513. }
  514. HRESULT
  515. CIISSecWizSettings::FetchProperties(
  516. IN CMetaKey & mk,
  517. IN LPCTSTR lpszPath, OPTIONAL
  518. IN BOOL fInherit OPTIONAL
  519. )
  520. /*++
  521. Routine Description:
  522. Fetch metabase properties that are applicable for the security wizard
  523. Arguments:
  524. CMetaKey & mk : open key
  525. LPCTSTR lpszPath : Optional path
  526. BOOL fInherit : TRUE to inherit properties
  527. Return Value:
  528. HRESULT
  529. --*/
  530. {
  531. CError err(mk.QueryResult());
  532. if (err.Succeeded())
  533. {
  534. if (m_pist != NULL)
  535. {
  536. //
  537. // Clean up existing template data (must
  538. // have pressed "back")
  539. //
  540. delete m_pist;
  541. }
  542. //
  543. // Create security template by calling the provided
  544. // allocator (which allocates an object of the
  545. // derived class which is service-specific)
  546. //
  547. m_pist = (*m_pfnTemplateAllocator)(&mk, lpszPath, fInherit);
  548. if (m_pist == NULL)
  549. {
  550. err = ERROR_NOT_ENOUGH_MEMORY;
  551. }
  552. else
  553. {
  554. err = m_pist->LoadData();
  555. }
  556. }
  557. return err;
  558. }
  559. //
  560. // Permissions Wizard Source Page
  561. //
  562. // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  563. IMPLEMENT_DYNCREATE(CPWSource, CIISWizardPage)
  564. CPWSource::CPWSource(
  565. IN CIISSecWizSettings * pSettings
  566. )
  567. /*++
  568. Routine Description:
  569. Constructor
  570. Arguments:
  571. CIISSecWizSettings * pSettings : Settings
  572. Return Value:
  573. None
  574. --*/
  575. : CIISWizardPage(
  576. CPWSource::IDD, // Template
  577. IDS_PERMWIZ, // Caption
  578. HEADER_PAGE // Header
  579. ),
  580. m_pSettings(pSettings)
  581. {
  582. //{{AFX_DATA_INIT(CPWSource)
  583. m_nSource = RADIO_INHERITANCE;
  584. //}}AFX_DATA_INIT
  585. ASSERT(m_pSettings);
  586. ASSERT(!m_pSettings->m_strServer.IsEmpty());
  587. }
  588. CPWSource::~CPWSource()
  589. /*++
  590. Routine Description:
  591. Destructor
  592. Arguments:
  593. N/A
  594. Return Value:
  595. N/A
  596. --*/
  597. {
  598. }
  599. void
  600. CPWSource::DoDataExchange(
  601. IN CDataExchange * pDX
  602. )
  603. /*++
  604. Routine Description:
  605. Initialise/Store control data
  606. Arguments:
  607. CDataExchange * pDX - DDX/DDV control structure
  608. Return Value:
  609. None
  610. --*/
  611. {
  612. CIISWizardPage::DoDataExchange(pDX);
  613. //{{AFX_DATA_MAP(CPWSource)
  614. DDX_Radio(pDX, IDC_RADIO_INHERIT, m_nSource);
  615. //}}AFX_DATA_MAP
  616. }
  617. void
  618. CPWSource::SetControlStates()
  619. /*++
  620. Routine Description:
  621. Set the state of the control data
  622. Arguments:
  623. None
  624. Return Value:
  625. None
  626. --*/
  627. {
  628. SetWizardButtons(PSWIZB_NEXT | PSWIZB_BACK);
  629. }
  630. //
  631. // Message Map
  632. //
  633. BEGIN_MESSAGE_MAP(CPWSource, CIISWizardPage)
  634. //{{AFX_MSG_MAP(CPWSource)
  635. //}}AFX_MSG_MAP
  636. END_MESSAGE_MAP()
  637. //
  638. // Message Handlers
  639. //
  640. // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  641. BOOL
  642. CPWSource::OnSetActive()
  643. /*++
  644. Routine Description:
  645. Activation handler
  646. Arguments:
  647. None
  648. Return Value:
  649. TRUE for success, FALSE for failure
  650. --*/
  651. {
  652. SetControlStates();
  653. return CIISWizardPage::OnSetActive();
  654. }
  655. LRESULT
  656. CPWSource::OnWizardNext()
  657. /*++
  658. Routine Description:
  659. 'next' handler. Store the source specified, so the next
  660. pages can skip or continue.
  661. Arguments:
  662. None
  663. Return Value:
  664. 0 to proceed, -1 to fail
  665. --*/
  666. {
  667. UpdateData(TRUE);
  668. m_pSettings->m_fUseTemplate = (m_nSource == RADIO_TEMPLATE);
  669. if (!m_pSettings->m_fUseTemplate)
  670. {
  671. CError err;
  672. CMetaKey mk(
  673. m_pSettings->m_strServer,
  674. METADATA_PERMISSION_READ,
  675. m_pSettings->m_strService,
  676. m_pSettings->m_dwInstance,
  677. m_pSettings->m_strParent,
  678. m_pSettings->m_strAlias
  679. );
  680. if (mk.IsHomeDirectoryPath())
  681. {
  682. //
  683. // Current path is a virtual server, and we're
  684. // at the home directory. We need to back up
  685. // twice.
  686. //
  687. err = mk.ConvertToParentPath(TRUE);
  688. ASSERT(err.Succeeded());
  689. }
  690. //
  691. // Convert to first parent path
  692. //
  693. err = mk.ConvertToParentPath(FALSE);
  694. if (err.Succeeded())
  695. {
  696. err = m_pSettings->FetchProperties(mk, NULL, TRUE);
  697. }
  698. if (err.MessageBoxOnFailure())
  699. {
  700. return -1;
  701. }
  702. }
  703. return CIISWizardPage::OnWizardNext();
  704. }
  705. //
  706. // Permissions Wizard Template Page
  707. //
  708. // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  709. IMPLEMENT_DYNCREATE(CPWTemplate, CIISWizardPage)
  710. CPWTemplate::CPWTemplate(
  711. IN CIISSecWizSettings * pSettings
  712. )
  713. /*++
  714. Routine Description:
  715. Constructor
  716. Arguments:
  717. CIISSecWizSettings * pSettings : Settings
  718. Return Value:
  719. None
  720. --*/
  721. : CIISWizardPage(
  722. CPWTemplate::IDD, // Template
  723. IDS_PERMWIZ, // Caption
  724. HEADER_PAGE // Header
  725. ),
  726. m_pSettings(pSettings)
  727. {
  728. //{{AFX_DATA_INIT(CPWTemplate)
  729. //}}AFX_DATA_INIT
  730. ASSERT(m_pSettings);
  731. ASSERT(!m_pSettings->m_strServer.IsEmpty());
  732. }
  733. CPWTemplate::~CPWTemplate()
  734. /*++
  735. Routine Description:
  736. Destructor
  737. Arguments:
  738. N/A
  739. Return Value:
  740. N/A
  741. --*/
  742. {
  743. }
  744. void
  745. CPWTemplate::DoDataExchange(
  746. IN CDataExchange * pDX
  747. )
  748. /*++
  749. Routine Description:
  750. Initialise/Store control data
  751. Arguments:
  752. CDataExchange * pDX - DDX/DDV control structure
  753. Return Value:
  754. None
  755. --*/
  756. {
  757. CIISWizardPage::DoDataExchange(pDX);
  758. //{{AFX_DATA_MAP(CPWTemplate)
  759. DDX_Control(pDX, IDC_LIST_TEMPLATES, m_list_Templates);
  760. DDX_Control(pDX, IDC_EDIT_DESCRIPTION, m_edit_Description);
  761. //}}AFX_DATA_MAP
  762. }
  763. void
  764. CPWTemplate::SetControlStates()
  765. /*++
  766. Routine Description:
  767. Set the state of the control data
  768. Arguments:
  769. None
  770. Return Value:
  771. None
  772. --*/
  773. {
  774. DWORD dwFlags = PSWIZB_BACK;
  775. int nSel = m_list_Templates.GetCurSel();
  776. if (nSel >= 0)
  777. {
  778. dwFlags |= PSWIZB_NEXT;
  779. }
  780. SetWizardButtons(dwFlags);
  781. }
  782. //
  783. // Message Map
  784. //
  785. BEGIN_MESSAGE_MAP(CPWTemplate, CIISWizardPage)
  786. //{{AFX_MSG_MAP(CPWTemplate)
  787. ON_LBN_SELCHANGE(IDC_LIST_TEMPLATES, OnSelchangeListTemplates)
  788. //}}AFX_MSG_MAP
  789. END_MESSAGE_MAP()
  790. //
  791. // Message Handlers
  792. //
  793. // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  794. BOOL
  795. CPWTemplate::OnSetActive()
  796. /*++
  797. Routine Description:
  798. Activation handler
  799. Arguments:
  800. None
  801. Return Value:
  802. TRUE to show the page, FALSE to skip it.
  803. --*/
  804. {
  805. if (!m_pSettings->m_fUseTemplate)
  806. {
  807. return FALSE;
  808. }
  809. SetControlStates();
  810. return CIISWizardPage::OnSetActive();
  811. }
  812. LRESULT
  813. CPWTemplate::OnWizardNext()
  814. /*++
  815. Routine Description:
  816. 'next' handler. Store the source specified, so the next
  817. pages can skip or continue.
  818. Arguments:
  819. None
  820. Return Value:
  821. 0 to proceed, -1 to fail
  822. --*/
  823. {
  824. UpdateData(TRUE);
  825. int nSel = m_list_Templates.GetCurSel();
  826. if (nSel < 0)
  827. {
  828. return -1;
  829. }
  830. CString strItem;
  831. m_list_Templates.GetText(nSel, strItem);
  832. //
  833. // Fetch the template, which is the text up until the tab
  834. // character
  835. //
  836. int nTab = strItem.Find(_T('\t'));
  837. ASSERT(nTab >= 0);
  838. if (nTab >= 0)
  839. {
  840. strItem.ReleaseBuffer(nTab);
  841. }
  842. TRACEEOLID(strItem);
  843. //
  844. // Read the properties from the selected template
  845. //
  846. CMetaKey mk(
  847. m_pSettings->m_strServer,
  848. METADATA_PERMISSION_READ,
  849. m_pSettings->m_strService,
  850. MASTER_INSTANCE,
  851. g_cszTemplates,
  852. strItem
  853. );
  854. CError err(m_pSettings->FetchProperties(mk, g_cszRoot, FALSE));
  855. if (err.MessageBoxOnFailure())
  856. {
  857. return -1;
  858. }
  859. return CIISWizardPage::OnWizardNext();
  860. }
  861. BOOL
  862. CPWTemplate::OnInitDialog()
  863. /*++
  864. Routine Description:
  865. WM_INITDIALOG handler. Initialize the dialog.
  866. Arguments:
  867. None.
  868. Return Value:
  869. TRUE if no focus is to be set automatically, FALSE if the focus
  870. is already set.
  871. --*/
  872. {
  873. CIISWizardPage::OnInitDialog();
  874. //
  875. // Assure the comments remain offscreen
  876. //
  877. m_list_Templates.SetTabStops(5000);
  878. //
  879. // Enumerate the existing templates
  880. //
  881. CMetaEnumerator mk(
  882. m_pSettings->m_strServer,
  883. m_pSettings->m_strService,
  884. MASTER_INSTANCE,
  885. g_cszTemplates
  886. );
  887. CError err(mk.QueryResult());
  888. if (err.Failed())
  889. {
  890. if (err.Win32Error() == ERROR_PATH_NOT_FOUND)
  891. {
  892. AfxMessageBox(IDS_NO_TEMPLATES);
  893. }
  894. else
  895. {
  896. err.MessageBox();
  897. }
  898. }
  899. else
  900. {
  901. //
  902. // Enumerate and add to the listbox.
  903. //
  904. CString strTemplate, strComment, strListItem;
  905. while (err.Succeeded())
  906. {
  907. err = mk.Next(strTemplate);
  908. if (err.Succeeded())
  909. {
  910. //
  911. // Read off the open key
  912. //
  913. err = mk.QueryValue(
  914. MD_SERVER_COMMENT,
  915. strComment,
  916. NULL,
  917. strTemplate
  918. );
  919. if (err.Succeeded())
  920. {
  921. TRACEEOLID(strComment);
  922. //
  923. // Append the comment in the off-screen
  924. // area of the listbox
  925. //
  926. strListItem.Format(_T("%s\t%s"),
  927. (LPCTSTR)strTemplate,
  928. (LPCTSTR)strComment
  929. );
  930. m_list_Templates.AddString(strListItem);
  931. }
  932. }
  933. }
  934. }
  935. return TRUE;
  936. }
  937. void
  938. CPWTemplate::OnSelchangeListTemplates()
  939. /*++
  940. Routine Description:
  941. Handle selection change in the templates listbox
  942. Arguments:
  943. None
  944. Return Value:
  945. None
  946. --*/
  947. {
  948. int nSel = m_list_Templates.GetCurSel();
  949. ASSERT(nSel >= 0);
  950. if (nSel >= 0)
  951. {
  952. CString strItem;
  953. m_list_Templates.GetText(nSel, strItem);
  954. //
  955. // Fetch the comment, which is just beyond the tab
  956. // character
  957. //
  958. int nTab = strItem.Find(_T('\t'));
  959. ASSERT(nTab >= 0);
  960. if (nTab >= 0)
  961. {
  962. strItem = strItem.Mid(nTab + 1);
  963. }
  964. m_edit_Description.SetWindowText(_T(""));
  965. m_edit_Description.SetWindowText(strItem);
  966. Invalidate();
  967. UpdateWindow();
  968. }
  969. SetControlStates();
  970. }
  971. //
  972. // Permissions Wizard ACL Page
  973. //
  974. // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  975. IMPLEMENT_DYNCREATE(CPWACL, CIISWizardPage)
  976. CPWACL::CPWACL(
  977. IN CIISSecWizSettings * pSettings
  978. )
  979. /*++
  980. Routine Description:
  981. Constructor
  982. Arguments:
  983. CIISSecWizSettings * pSettings : Settings
  984. Return Value:
  985. None
  986. --*/
  987. : CIISWizardPage(
  988. CPWACL::IDD, // Template
  989. IDS_PERMWIZ, // Caption,
  990. HEADER_PAGE // Header
  991. ),
  992. m_pSettings(pSettings)
  993. {
  994. //{{AFX_DATA_INIT(CPWACL)
  995. m_nRadioAclType = RADIO_MAXIMUM;
  996. //}}AFX_DATA_INIT
  997. ASSERT(m_pSettings);
  998. ASSERT(!m_pSettings->m_strServer.IsEmpty());
  999. }
  1000. CPWACL::~CPWACL()
  1001. /*++
  1002. Routine Description:
  1003. Destructor
  1004. Arguments:
  1005. N/A
  1006. Return Value:
  1007. N/A
  1008. --*/
  1009. {
  1010. }
  1011. void
  1012. CPWACL::DoDataExchange(
  1013. IN CDataExchange * pDX
  1014. )
  1015. /*++
  1016. Routine Description:
  1017. Initialise/Store control data
  1018. Arguments:
  1019. CDataExchange * pDX - DDX/DDV control structure
  1020. Return Value:
  1021. None
  1022. --*/
  1023. {
  1024. CIISWizardPage::DoDataExchange(pDX);
  1025. //{{AFX_DATA_MAP(CPWACL)
  1026. DDX_Control(pDX, IDC_ED_BOLD4, m_static_Line4);
  1027. DDX_Control(pDX, IDC_ED_BOLD3, m_static_Line3);
  1028. DDX_Control(pDX, IDC_ED_BOLD2, m_static_Line2);
  1029. DDX_Control(pDX, IDC_ED_BOLD1, m_static_Line1);
  1030. DDX_Radio(pDX, IDC_RADIO_ACL_MAXIMUM, m_nRadioAclType);
  1031. //}}AFX_DATA_MAP
  1032. }
  1033. void
  1034. CPWACL::SetControlStates()
  1035. /*++
  1036. Routine Description:
  1037. Set the state of the control data
  1038. Arguments:
  1039. None
  1040. Return Value:
  1041. None
  1042. --*/
  1043. {
  1044. SetWizardButtons(PSWIZB_NEXT | PSWIZB_BACK);
  1045. }
  1046. //
  1047. // Message Map
  1048. //
  1049. BEGIN_MESSAGE_MAP(CPWACL, CIISWizardPage)
  1050. //{{AFX_MSG_MAP(CPWACL)
  1051. //}}AFX_MSG_MAP
  1052. END_MESSAGE_MAP()
  1053. BOOL
  1054. GetPhysicalPath(
  1055. IN CMetaKey & mk,
  1056. IN CString & strMetaPath,
  1057. OUT CString & strPhysicalPath
  1058. )
  1059. /*++
  1060. Routine Description:
  1061. Get the physical path of the parent as described by the metabase path
  1062. Arguments:
  1063. CMetaKey & mk : Open metabase key
  1064. CString & strMetaPath : Metabase path
  1065. CString & strPhysicalPath : Returns physical path
  1066. Return Value:
  1067. TRUE for success, FALSE for failure
  1068. --*/
  1069. {
  1070. //
  1071. // Get physical path of parent
  1072. //
  1073. CString strAlias;
  1074. int nSlash = strMetaPath.ReverseFind(SZ_MBN_SEP_CHAR);
  1075. if (nSlash < 0)
  1076. {
  1077. //
  1078. // Didn't encounter a physical path at all!
  1079. //
  1080. TRACEEOLID("No physical path established -- ACLS skipped");
  1081. ASSERT(FALSE);
  1082. return FALSE;
  1083. }
  1084. strAlias = strMetaPath.Mid(nSlash + 1);
  1085. strMetaPath.ReleaseBuffer(nSlash);
  1086. TRACEEOLID(strAlias);
  1087. TRACEEOLID(strMetaPath);
  1088. BOOL fInherit = FALSE;
  1089. CError err(mk.QueryValue(
  1090. MD_VR_PATH,
  1091. strPhysicalPath,
  1092. &fInherit,
  1093. strMetaPath
  1094. ));
  1095. if (err.Failed())
  1096. {
  1097. GetPhysicalPath(mk, strMetaPath, strPhysicalPath);
  1098. }
  1099. strPhysicalPath += _T("\\");
  1100. strPhysicalPath += strAlias;
  1101. return TRUE;
  1102. }
  1103. //
  1104. // Message Handlers
  1105. //
  1106. // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  1107. LRESULT
  1108. CPWACL::OnWizardNext()
  1109. /*++
  1110. Routine Description:
  1111. 'next' handler. Store the acl replacement type specified, so the next
  1112. pages can skip or continue.
  1113. Arguments:
  1114. None
  1115. Return Value:
  1116. 0 to proceed, -1 to fail
  1117. --*/
  1118. {
  1119. UpdateData(TRUE);
  1120. switch(m_nRadioAclType)
  1121. {
  1122. case RADIO_MINIMUM:
  1123. m_pSettings->m_fReplaceAcls = FALSE;
  1124. break;
  1125. case RADIO_MAXIMUM:
  1126. m_pSettings->m_fReplaceAcls = TRUE;
  1127. break;
  1128. case RADIO_NONE:
  1129. default:
  1130. m_pSettings->m_fSetAcls = FALSE;
  1131. }
  1132. return CIISWizardPage::OnWizardNext();
  1133. }
  1134. static PSID psidAdministrators = NULL;
  1135. static PSID psidEveryone = NULL;
  1136. BOOL
  1137. CPWACL::OnSetActive()
  1138. /*++
  1139. Routine Description:
  1140. Activation handler
  1141. Arguments:
  1142. None
  1143. Return Value:
  1144. TRUE to show the page, FALSE to skip it.
  1145. --*/
  1146. {
  1147. //
  1148. // Assume no acls until all tests pass
  1149. //
  1150. m_pSettings->m_fSetAcls = FALSE;
  1151. if (!IsServerLocal(m_pSettings->m_strServer))
  1152. {
  1153. TRACEEOLID("We're not local -- skipping ACL phase");
  1154. return FALSE;
  1155. }
  1156. //
  1157. // Get properties on the current directory object
  1158. //
  1159. CChildNodeProps props(
  1160. m_pSettings->m_strServer,
  1161. m_pSettings->m_strService,
  1162. m_pSettings->m_dwInstance,
  1163. m_pSettings->m_strParent,
  1164. m_pSettings->m_strAlias,
  1165. WITH_INHERITANCE
  1166. );
  1167. CError err(props.LoadData());
  1168. if (err.MessageBoxOnFailure())
  1169. {
  1170. TRACEEOLID("Unable to determine directory properties -- skipping ACLS");
  1171. ASSERT(FALSE);
  1172. return FALSE;
  1173. }
  1174. m_pSettings->m_fRedirected = props.IsRedirected();
  1175. if (m_pSettings->m_fRedirected)
  1176. {
  1177. TRACEEOLID("Redirection in place, will not set ACLS");
  1178. return FALSE;
  1179. }
  1180. //
  1181. // If the path is on a remote store, Then no ACL page. - boydm
  1182. //
  1183. if (::IsUNCName(MP_V(props.m_strPath)))
  1184. {
  1185. TRACEEOLID("share is remote, will not set ACLS");
  1186. return FALSE;
  1187. }
  1188. //
  1189. // Don't get confused here, build the real physical path
  1190. //
  1191. if (props.IsPathInherited())
  1192. {
  1193. TRACEEOLID("Path inherited");
  1194. //
  1195. // Look for parent path.
  1196. //
  1197. CString strMetaPath(props.QueryMetaRoot());
  1198. TRACEEOLID(strMetaPath);
  1199. CMetaKey mk(m_pSettings->m_strServer);
  1200. err = mk.QueryResult();
  1201. if (err.Failed())
  1202. {
  1203. ASSERT(FALSE);
  1204. return FALSE;
  1205. }
  1206. if (!GetPhysicalPath(mk, strMetaPath, m_pSettings->m_strPath))
  1207. {
  1208. ASSERT(FALSE);
  1209. return FALSE;
  1210. }
  1211. }
  1212. else
  1213. {
  1214. m_pSettings->m_strPath = props.m_strPath;
  1215. }
  1216. DWORD dwFileSystemFlags;
  1217. if (::GetVolumeInformationSystemFlags(
  1218. m_pSettings->m_strPath,
  1219. &dwFileSystemFlags
  1220. ))
  1221. {
  1222. if (!(dwFileSystemFlags & FS_PERSISTENT_ACLS))
  1223. {
  1224. //
  1225. // No ACLS
  1226. //
  1227. TRACEEOLID("Volume type doesn't accept ACLS -- skipping");
  1228. return FALSE;
  1229. }
  1230. }
  1231. //
  1232. // Build ACL information to be set
  1233. //
  1234. m_pSettings->m_AccessMaskAdmin = ACCMASK_ADMIN_FLAGS;
  1235. m_pSettings->m_AccessMaskDefault
  1236. = m_pSettings->m_AccessMaskEveryone = ACC_MASK_EVERYONE_FLAGS;
  1237. //
  1238. // Display proposed ACEs in bold-faced entries on the dialog
  1239. //
  1240. UINT nID = IDC_ED_BOLD1;
  1241. CString str;
  1242. VERIFY(str.LoadString(IDS_ACL_ADMINS));
  1243. GetDlgItem(nID++)->SetWindowText(str);
  1244. if (IS_FLAG_SET(m_pSettings->m_pist->m_dwAccessPerms, MD_ACCESS_READ))
  1245. {
  1246. VERIFY(str.LoadString(IDS_ACL_EV_READ));
  1247. GetDlgItem(nID++)->SetWindowText(str);
  1248. m_pSettings->m_AccessMaskEveryone |= ACCMASK_READ_FLAGS;
  1249. }
  1250. if (IS_FLAG_SET(m_pSettings->m_pist->m_dwAccessPerms, MD_ACCESS_WRITE))
  1251. {
  1252. VERIFY(str.LoadString(IDS_ACL_EV_WRITE));
  1253. GetDlgItem(nID++)->SetWindowText(str);
  1254. m_pSettings->m_AccessMaskEveryone |= ACCMASK_WRITE_FLAGS;
  1255. }
  1256. if (IS_FLAG_SET(m_pSettings->m_pist->m_dwAccessPerms, MD_ACCESS_EXECUTE))
  1257. {
  1258. VERIFY(str.LoadString(IDS_ACL_EV_EXEC));
  1259. GetDlgItem(nID++)->SetWindowText(str);
  1260. m_pSettings->m_AccessMaskEveryone |= ACCMASK_EXEC_FLAGS;
  1261. }
  1262. ZeroMemory(&m_pSettings->m_rgaae, sizeof(m_pSettings->m_rgaae));
  1263. SID_IDENTIFIER_AUTHORITY siaNtAuthority = SECURITY_NT_AUTHORITY;
  1264. SID_IDENTIFIER_AUTHORITY siaWorldSidAuthority = SECURITY_WORLD_SID_AUTHORITY;
  1265. AllocateAndInitializeSid(
  1266. &siaNtAuthority,
  1267. 2,
  1268. SECURITY_BUILTIN_DOMAIN_RID,
  1269. DOMAIN_ALIAS_RID_ADMINS,
  1270. 0, 0, 0, 0, 0, 0,
  1271. &psidAdministrators);
  1272. AllocateAndInitializeSid(
  1273. &siaWorldSidAuthority,
  1274. 1,
  1275. SECURITY_WORLD_RID,
  1276. 0, 0, 0, 0, 0, 0, 0,
  1277. &psidEveryone);
  1278. //
  1279. // Set up permissions for the "Everyone" group
  1280. //
  1281. m_pSettings->m_rgaae[0].Trustee.pMultipleTrustee = NULL;
  1282. m_pSettings->m_rgaae[0].Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
  1283. m_pSettings->m_rgaae[0].Trustee.TrusteeForm = TRUSTEE_IS_SID;
  1284. m_pSettings->m_rgaae[0].Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
  1285. m_pSettings->m_rgaae[0].Trustee.ptstrName = (LPTSTR)psidEveryone;
  1286. m_pSettings->m_rgaae[0].grfAccessMode = SET_ACCESS;
  1287. m_pSettings->m_rgaae[0].grfAccessPermissions = m_pSettings->m_AccessMaskEveryone;
  1288. m_pSettings->m_rgaae[0].grfInheritance = SUB_CONTAINERS_AND_OBJECTS_INHERIT;
  1289. //
  1290. // Set up permissions for the "Administrators" group
  1291. //
  1292. m_pSettings->m_rgaae[1].Trustee.pMultipleTrustee = NULL;
  1293. m_pSettings->m_rgaae[1].Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
  1294. m_pSettings->m_rgaae[1].Trustee.TrusteeForm = TRUSTEE_IS_SID;
  1295. m_pSettings->m_rgaae[1].Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
  1296. m_pSettings->m_rgaae[1].Trustee.ptstrName = (LPTSTR)psidAdministrators;
  1297. m_pSettings->m_rgaae[1].grfAccessMode = SET_ACCESS;
  1298. m_pSettings->m_rgaae[1].grfAccessPermissions = m_pSettings->m_AccessMaskAdmin;
  1299. m_pSettings->m_rgaae[1].grfInheritance = SUB_CONTAINERS_AND_OBJECTS_INHERIT;
  1300. SetControlStates();
  1301. //
  1302. // Passed all tests, we'll give the option to set ACLS
  1303. //
  1304. m_pSettings->m_fSetAcls = TRUE;
  1305. return CIISWizardPage::OnSetActive();
  1306. }
  1307. //
  1308. // Permissions Wizard Template Page
  1309. //
  1310. // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  1311. IMPLEMENT_DYNCREATE(CPWSummary, CIISWizardPage)
  1312. CPWSummary::CPWSummary(
  1313. IN CIISSecWizSettings * pSettings
  1314. )
  1315. /*++
  1316. Routine Description:
  1317. Constructor
  1318. Arguments:
  1319. CIISSecWizSettings * pSettings : Settings
  1320. Return Value:
  1321. None
  1322. --*/
  1323. : CIISWizardPage(
  1324. CPWSummary::IDD, // Template
  1325. IDS_PERMWIZ, // Caption
  1326. HEADER_PAGE // Header
  1327. ),
  1328. m_pSettings(pSettings)
  1329. {
  1330. //{{AFX_DATA_INIT(CPWSummary)
  1331. //}}AFX_DATA_INIT
  1332. ASSERT(m_pSettings);
  1333. ASSERT(!m_pSettings->m_strServer.IsEmpty());
  1334. }
  1335. CPWSummary::~CPWSummary()
  1336. /*++
  1337. Routine Description:
  1338. Destructor
  1339. Arguments:
  1340. N/A
  1341. Return Value:
  1342. N/A
  1343. --*/
  1344. {
  1345. }
  1346. void
  1347. CPWSummary::DoDataExchange(
  1348. IN CDataExchange * pDX
  1349. )
  1350. /*++
  1351. Routine Description:
  1352. Initialise/Store control data
  1353. Arguments:
  1354. CDataExchange * pDX - DDX/DDV control structure
  1355. Return Value:
  1356. None
  1357. --*/
  1358. {
  1359. CIISWizardPage::DoDataExchange(pDX);
  1360. //{{AFX_DATA_MAP(CPWSummary)
  1361. DDX_Control(pDX, IDC_LIST_SUMMARY, m_list_Summary);
  1362. //}}AFX_DATA_MAP
  1363. }
  1364. void
  1365. CPWSummary::SetControlStates()
  1366. /*++
  1367. Routine Description:
  1368. Set the state of the control data
  1369. Arguments:
  1370. None
  1371. Return Value:
  1372. None
  1373. --*/
  1374. {
  1375. SetWizardButtons(PSWIZB_NEXT | PSWIZB_BACK);
  1376. }
  1377. //
  1378. // Message Map
  1379. //
  1380. BEGIN_MESSAGE_MAP(CPWSummary, CIISWizardPage)
  1381. //{{AFX_MSG_MAP(CPWSummary)
  1382. //}}AFX_MSG_MAP
  1383. END_MESSAGE_MAP()
  1384. void
  1385. CPWSummary::GenerateAclSummary()
  1386. /*++
  1387. Routine Description:
  1388. Break down ACL list into the summary
  1389. Arguments:
  1390. None
  1391. Return Value:
  1392. None
  1393. --*/
  1394. {
  1395. //
  1396. // Summarize ACL Settings:
  1397. //
  1398. int nIndentLevel = 0;
  1399. if (m_pSettings->m_fSetAcls)
  1400. {
  1401. m_pSettings->m_pist->AddSummaryString(
  1402. m_pSettings->m_fReplaceAcls
  1403. ? IDS_ACL_REPLACEMENT
  1404. : IDS_ACL_ADDED,
  1405. nIndentLevel++
  1406. );
  1407. m_pSettings->m_pist->AddSummaryString(IDS_ACL_ADMIN, nIndentLevel);
  1408. m_pSettings->m_pist->AddSummaryString(IDS_ACL_EVR, nIndentLevel++);
  1409. // if (m_pSettings->m_AccessMaskEveryone
  1410. // == m_pSettings->m_AccessMaskDefault)
  1411. // {
  1412. // //
  1413. // // "Everyone" has zero access
  1414. // //
  1415. // m_pSettings->m_pist->AddSummaryString(
  1416. // IDS_SUMMARY_NONE,
  1417. // nIndentLevel
  1418. // );
  1419. // }
  1420. // else
  1421. // {
  1422. //
  1423. // Enumerate the specific rights granted
  1424. // to "everyone"
  1425. //
  1426. for (int i = 0; i < ARRAY_SIZE(fsAclFlags); ++i)
  1427. {
  1428. if (IS_FLAG_SET(
  1429. m_pSettings->m_AccessMaskEveryone,
  1430. fsAclFlags[i].dwFlag
  1431. ) == fsAclFlags[i].fSet)
  1432. {
  1433. m_pSettings->m_pist->AddSummaryString(
  1434. fsAclFlags[i].nID,
  1435. nIndentLevel
  1436. );
  1437. }
  1438. }
  1439. // }
  1440. }
  1441. else
  1442. {
  1443. m_pSettings->m_pist->AddSummaryString(IDS_ACL_NONE, nIndentLevel);
  1444. }
  1445. }
  1446. void
  1447. CPWSummary::DisplaySummary()
  1448. /*++
  1449. Routine Description:
  1450. Break down the security settings and display them in text
  1451. form in the summary listbox.
  1452. Arguments:
  1453. None
  1454. Return Value:
  1455. None.
  1456. --*/
  1457. {
  1458. //
  1459. // Generate Summary
  1460. //
  1461. m_pSettings->m_pist->ClearSummary();
  1462. m_pSettings->m_pist->GenerateSummary(
  1463. m_pSettings->m_fUseTemplate,
  1464. m_pSettings->m_strServer,
  1465. m_pSettings->m_strService,
  1466. m_pSettings->m_dwInstance,
  1467. m_pSettings->m_strParent,
  1468. m_pSettings->m_strAlias
  1469. );
  1470. GenerateAclSummary();
  1471. //
  1472. // Display it in the listbox
  1473. //
  1474. m_list_Summary.ResetContent();
  1475. POSITION pos = m_pSettings->m_pist->GetHeadPosition();
  1476. while(pos)
  1477. {
  1478. CString & str = m_pSettings->m_pist->GetNext(pos);
  1479. m_list_Summary.AddString(str);
  1480. }
  1481. }
  1482. //
  1483. // Message Handlers
  1484. //
  1485. // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  1486. BOOL
  1487. CPWSummary::OnSetActive()
  1488. /*++
  1489. Routine Description:
  1490. Activation handler
  1491. Arguments:
  1492. None
  1493. Return Value:
  1494. TRUE for success, FALSE for failure
  1495. --*/
  1496. {
  1497. SetControlStates();
  1498. DisplaySummary();
  1499. return CIISWizardPage::OnSetActive();
  1500. }
  1501. /* virtual */
  1502. LRESULT
  1503. CPWSummary::OnWizardNext()
  1504. /*++
  1505. Routine Description:
  1506. 'Next' button handler. Force the control data to be stored
  1507. Arguments:
  1508. None
  1509. Return Value:
  1510. 0 to proceed, -1 to fail
  1511. --*/
  1512. {
  1513. //
  1514. // Store everything here
  1515. //
  1516. CError err(m_pSettings->m_pist->ApplySettings(
  1517. m_pSettings->m_fUseTemplate,
  1518. m_pSettings->m_strServer,
  1519. m_pSettings->m_strService,
  1520. m_pSettings->m_dwInstance,
  1521. m_pSettings->m_strParent,
  1522. m_pSettings->m_strAlias
  1523. ));
  1524. //
  1525. // Set the ACLS
  1526. //
  1527. if (err.Succeeded() && m_pSettings->m_fSetAcls)
  1528. {
  1529. err = ApplyACLSToFiles();
  1530. }
  1531. //
  1532. // Store the error for the completion page
  1533. //
  1534. m_pSettings->m_hResult = err;
  1535. return CIISWizardPage::OnWizardNext();
  1536. }
  1537. HRESULT
  1538. CPWSummary::ApplyACLSToFiles()
  1539. /*++
  1540. Routine Description:
  1541. Apply ACLS to files
  1542. Arguments:
  1543. None
  1544. Return Value:
  1545. HRESULT
  1546. --*/
  1547. {
  1548. CError err;
  1549. SECURITY_INFORMATION si = 0;
  1550. SECURITY_DESCRIPTOR * psd = NULL;
  1551. PACL pOldDacl = NULL, pNewDacl = NULL;;
  1552. //
  1553. // Can take a while.
  1554. //
  1555. CWaitCursor waitcursor;
  1556. do
  1557. {
  1558. err = GetNamedSecurityInfo(
  1559. (LPTSTR)(LPCTSTR)m_pSettings->m_strPath,
  1560. SE_FILE_OBJECT,
  1561. DACL_SECURITY_INFORMATION,
  1562. NULL, // owner SID
  1563. NULL, // group SID
  1564. &pOldDacl, // pointer to the DACL
  1565. NULL, // pointer to the SACL
  1566. (PVOID *)&psd
  1567. );
  1568. BREAK_ON_ERR_FAILURE(err);
  1569. if (!m_pSettings->m_fReplaceAcls)
  1570. {
  1571. m_pSettings->m_rgaae[0].grfAccessMode = GRANT_ACCESS;
  1572. m_pSettings->m_rgaae[1].grfAccessMode = GRANT_ACCESS;
  1573. }
  1574. // Prepare DACL according to template
  1575. err = SetEntriesInAcl(
  1576. ARRAY_SIZE(m_pSettings->m_rgaae),
  1577. m_pSettings->m_rgaae,
  1578. m_pSettings->m_fReplaceAcls ? NULL : pOldDacl,
  1579. &pNewDacl
  1580. );
  1581. BREAK_ON_ERR_FAILURE(err);
  1582. // Set permissions on the selected object
  1583. si |= DACL_SECURITY_INFORMATION;
  1584. si |= PROTECTED_DACL_SECURITY_INFORMATION;
  1585. err = HRESULT_FROM_WIN32(SetNamedSecurityInfo(
  1586. (LPTSTR)(LPCTSTR)m_pSettings->m_strPath,
  1587. SE_FILE_OBJECT,
  1588. si,
  1589. NULL,
  1590. NULL,
  1591. pNewDacl,
  1592. NULL));
  1593. BREAK_ON_ERR_FAILURE(err);
  1594. // For children of this object we should set empty DACL
  1595. // if we need only permissions inherited from parent
  1596. if (PathIsDirectory(m_pSettings->m_strPath))
  1597. {
  1598. if (m_pSettings->m_fReplaceAcls)
  1599. {
  1600. // Build security descriptor with empty DACL
  1601. ACL daclEmpty = {0};
  1602. InitializeAcl(&daclEmpty, sizeof(ACL), ACL_REVISION);
  1603. si = 0;
  1604. si |= DACL_SECURITY_INFORMATION;
  1605. si |= UNPROTECTED_DACL_SECURITY_INFORMATION;
  1606. err = SetPermToChildren(
  1607. m_pSettings->m_strPath,
  1608. si,
  1609. &daclEmpty,
  1610. NULL);
  1611. BREAK_ON_ERR_FAILURE(err);
  1612. }
  1613. }
  1614. // In other cases children should inherit permissions from the parent
  1615. }
  1616. while(FALSE);
  1617. if (pOldDacl != NULL)
  1618. {
  1619. LocalFree(pOldDacl);
  1620. }
  1621. if (pNewDacl != NULL)
  1622. {
  1623. LocalFree(pNewDacl);
  1624. }
  1625. if (psd != NULL)
  1626. {
  1627. LocalFree(psd);
  1628. }
  1629. return err;
  1630. }
  1631. BOOL
  1632. CPWSummary::OnInitDialog()
  1633. /*++
  1634. Routine Description:
  1635. WM_INITDIALOG handler. Initialize the dialog.
  1636. Arguments:
  1637. None.
  1638. Return Value:
  1639. TRUE if no focus is to be set automatically, FALSE if the focus
  1640. is already set.
  1641. --*/
  1642. {
  1643. CIISWizardPage::OnInitDialog();
  1644. //
  1645. // Set the tabs based on the hidden column headers
  1646. //
  1647. CRect rc1, rc2;
  1648. GetDlgItem(IDC_STATIC_TAB2)->GetWindowRect(&rc2);
  1649. GetDlgItem(IDC_STATIC_TAB1)->GetWindowRect(&rc1);
  1650. m_list_Summary.SetTabStops(((LPRECT)rc2)->left - ((LPRECT)rc1)->left);
  1651. return TRUE;
  1652. }
  1653. HRESULT
  1654. COMDLL_ISMSecurityWizard(
  1655. IN pfnNewSecurityTemplate pfnTemplateAllocator,
  1656. IN CMetaInterface * pInterface,
  1657. IN UINT nLeftBmpId,
  1658. IN UINT nHeadBmpId,
  1659. IN LPCTSTR lpszService,
  1660. IN DWORD dwInstance,
  1661. IN LPCTSTR lpszParent,
  1662. IN LPCTSTR lpszAlias
  1663. )
  1664. /*++
  1665. Routine Description:
  1666. Launch the security wizard
  1667. Arguments:
  1668. pfnNewSecurityTemplate pfnTemplateAllocator : Function to allocate template.
  1669. CMetaInterface * pInterface : Existing interface
  1670. LPCTSTR lpszService : Service name
  1671. DWORD dwInstance : Parent instance
  1672. LPCTSTR lpszParent : Parent path
  1673. LPCTSTR lpszAlias : Child to configure or NULL
  1674. Return Value:
  1675. HRESULT
  1676. --*/
  1677. {
  1678. CError err;
  1679. ASSERT(pInterface != NULL);
  1680. LPCTSTR lpszServer = pInterface->QueryServerName();
  1681. ASSERT(lpszServer != NULL);
  1682. //
  1683. // Only run wizard if they are an administrator - boydm
  1684. //
  1685. BOOL fAdmin;
  1686. err = DetermineIfAdministrator(
  1687. pInterface,
  1688. lpszService,
  1689. dwInstance,
  1690. &fAdmin
  1691. );
  1692. if (err.Failed() || !fAdmin)
  1693. {
  1694. AfxMessageBox(IDS_ACL_ADMINS);
  1695. return err;
  1696. }
  1697. CIISWizardSheet sheet(nLeftBmpId, nHeadBmpId);
  1698. //
  1699. // Create security wizard settings object
  1700. //
  1701. CIISSecWizSettings sws(
  1702. pfnTemplateAllocator,
  1703. lpszServer,
  1704. lpszService,
  1705. dwInstance,
  1706. lpszParent,
  1707. lpszAlias
  1708. );
  1709. CIISWizardBookEnd pgWelcome(IDS_PWIZ_WELCOME, IDS_PERMWIZ, IDS_PWIZ_BODY);
  1710. CPWSource pgSource(&sws);
  1711. CPWTemplate pgTemplate(&sws);
  1712. CPWACL pgACL(&sws);
  1713. CPWSummary pgSummary(&sws);
  1714. CIISWizardBookEnd pgCompletion(
  1715. &sws.m_hResult,
  1716. IDS_PWIZ_SUCCESS,
  1717. IDS_PWIZ_FAILURE,
  1718. IDS_PERMWIZ
  1719. );
  1720. sheet.AddPage(&pgWelcome);
  1721. sheet.AddPage(&pgSource);
  1722. sheet.AddPage(&pgTemplate);
  1723. sheet.AddPage(&pgACL);
  1724. sheet.AddPage(&pgSummary);
  1725. sheet.AddPage(&pgCompletion);
  1726. sheet.DoModal();
  1727. return err;
  1728. }