Leaked source code of windows server 2003
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.

2039 lines
59 KiB

  1. /*++
  2. Copyright (c) 2001 Microsoft Corporation
  3. Module Name :
  4. webcomp.cxx
  5. Abstract:
  6. Class used to install the World Wide Web component
  7. Author:
  8. Christopher Achille (cachille)
  9. Project:
  10. Internet Services Setup
  11. Revision History:
  12. April 2002: Created
  13. --*/
  14. #include "stdafx.h"
  15. #include "webcomp.hxx"
  16. #include "acl.hxx"
  17. #include "iadm.h"
  18. #include "iiscnfgp.h"
  19. #include "mdkey.h"
  20. #include "mdentry.h"
  21. #include "restrlst.hxx"
  22. #include "svc.h"
  23. #include "reg.hxx"
  24. #include "ACShim.h"
  25. #include "Setuser.h"
  26. #include "lockdown.hxx"
  27. #include "helper.h"
  28. #include "Wtsapi32.h" // TS settings
  29. #include "Mprapi.h" // RAS/VPN Settings
  30. #include "lockdown.hxx"
  31. #include <secconlib.h>
  32. #include <shlwapi.h>
  33. #include "inetinfo.h"
  34. #include "resource.h"
  35. // Undef this becase of collision with TSTR::PathAppend
  36. #ifdef PathAppend
  37. #undef PathAppend
  38. #endif
  39. // Local const definitions
  40. //
  41. LPCWSTR IIS_WPG_GROUPNAME = L"IIS_WPG";
  42. LPCWSTR OLD_WAM_GROUPNAME = L"Web Applications";
  43. const LPTSTR MofCompFiles[] =
  44. { { _T("asp.mof") },
  45. { _T("w3core.mof") },
  46. { _T("w3isapi.mof") },
  47. { NULL } };
  48. sOurDefaultExtensions CWebServiceInstallComponent::m_aExternalExt[ CWebServiceInstallComponent::EXTENSIONS_EXTERNAL ] =
  49. {
  50. { _T("idq.dll"),
  51. _T("IndexingService"),
  52. IDS_PRODUCT_INDEXSERVICE,
  53. NULL, // No component name - we don't install this
  54. FALSE, // UI deletable
  55. FALSE, // Disabled
  56. { _T(".idq"),
  57. _T(".ida"),
  58. NULL
  59. }
  60. },
  61. { _T("webhits.dll"),
  62. _T("IndexingService"),
  63. IDS_PRODUCT_INDEXSERVICE,
  64. NULL, // No component name - we don't install this
  65. FALSE, // UI deletable
  66. FALSE, // Disabled
  67. { _T(".htw"),
  68. NULL
  69. }
  70. },
  71. { _T("msw3prt.dll"),
  72. _T("W3PRT"),
  73. IDS_PRODUCT_INETPRINT,
  74. NULL, // No component name - we don't install this
  75. FALSE, // UI deletable
  76. FALSE, // Disabled
  77. { _T(".printer"),
  78. NULL
  79. }
  80. }
  81. };
  82. // Constructor
  83. //
  84. CWebServiceInstallComponent::CWebServiceInstallComponent()
  85. {
  86. m_bMofCompRun = FALSE;
  87. m_bWebDavIsDisabled = FALSE;
  88. }
  89. // GetName
  90. //
  91. // Return the name for the Web Service Component
  92. //
  93. LPTSTR
  94. CWebServiceInstallComponent::GetName()
  95. {
  96. return _T("iis_www");
  97. }
  98. // GetFriendlyName
  99. //
  100. // Get the Friendly name for the UI
  101. //
  102. BOOL
  103. CWebServiceInstallComponent::GetFriendlyName( TSTR *pstrFriendlyName )
  104. {
  105. return pstrFriendlyName->LoadString( IDS_DTC_WORLDWIDEWEB );
  106. }
  107. // SetWWWRootAclonDir
  108. //
  109. // Set the WWW Root Acl that we need. This will be used for WWWRoot
  110. // and the customer error pages root
  111. //
  112. // The acl is the following:
  113. // Upgrades - Add IIS_WPG:R
  114. // Fresh Install - <Deny> IUSR_MACHINENAME:Write+Delete
  115. // <Allow> Users:Read+Execute
  116. // <Allow> IIS_WPG:Read+Execute
  117. // <Allow> Administrators:Full
  118. // <Allow> LocalSystem:Full
  119. //
  120. // Parameters:
  121. // szPhysicalPath - The Physical Path to add the ACL
  122. // bAddIusrDeny - Should we add the IUSR_ deny acl?
  123. //
  124. // Return:
  125. // TRUE - Success
  126. // FALSE - Failure
  127. BOOL
  128. CWebServiceInstallComponent::SetWWWRootAclonDir(LPTSTR szPhysicalPath,
  129. BOOL bAddIusrDeny)
  130. {
  131. CSecurityDescriptor PathSD;
  132. iisDebugOut((LOG_TYPE_PROGRAM_FLOW, _T("Calling SetWWWRootAclonDir\n")));
  133. if ( IsUpgrade() )
  134. {
  135. // Upgrade
  136. if ( !PathSD.GetSecurityInfoOnFile( szPhysicalPath ) )
  137. {
  138. // Failed to retrieve old SD
  139. return FALSE;
  140. }
  141. }
  142. else
  143. {
  144. // Fresh Install
  145. if ( !PathSD.AddAccessAcebyWellKnownID( CSecurityDescriptor::GROUP_USERS,
  146. CSecurityDescriptor::ACCESS_READ_EXECUTE,
  147. TRUE,
  148. TRUE ) ||
  149. !PathSD.AddAccessAcebyWellKnownID( CSecurityDescriptor::GROUP_ADMINISTRATORS,
  150. CSecurityDescriptor::ACCESS_FULL,
  151. TRUE,
  152. TRUE ) ||
  153. !PathSD.AddAccessAcebyWellKnownID( CSecurityDescriptor::USER_LOCALSYSTEM,
  154. CSecurityDescriptor::ACCESS_FULL,
  155. TRUE,
  156. TRUE )
  157. )
  158. {
  159. // Failed ot create SD
  160. return FALSE;
  161. }
  162. if ( bAddIusrDeny &&
  163. !PathSD.AddAccessAcebyName( g_pTheApp->m_csGuestName.GetBuffer(0),
  164. CSecurityDescriptor::ACCESS_WRITEONLY |
  165. CSecurityDescriptor::ACCESS_DIR_DELETE,
  166. FALSE,
  167. TRUE ) )
  168. {
  169. // Failed to add IUSR_
  170. return FALSE;
  171. }
  172. }
  173. if ( !PathSD.AddAccessAcebyName( _T("IIS_WPG"),
  174. CSecurityDescriptor::ACCESS_READ_EXECUTE,
  175. TRUE,
  176. TRUE ) )
  177. {
  178. // Failed to add IIS_WPG
  179. return FALSE;
  180. }
  181. if ( !CreateDirectoryWithSA( szPhysicalPath, PathSD, FALSE ) )
  182. {
  183. // Failed to set ACL on file/dir
  184. return FALSE;
  185. }
  186. return TRUE;
  187. }
  188. // SetPassportAcls
  189. //
  190. // Set the appropriate Passport Acl's
  191. //
  192. // Parameters
  193. // bAdd - TRUE == Add Acl
  194. // FALSE == Remove Acl
  195. //
  196. BOOL
  197. CWebServiceInstallComponent::SetPassportAcls( BOOL bAdd )
  198. {
  199. BOOL bIsAclable;
  200. TSTR_PATH strPassportDir;
  201. CSecurityDescriptor sdPassport;
  202. iisDebugOut((LOG_TYPE_PROGRAM_FLOW, _T("Calling SetPassportAcls\n")));
  203. if ( !strPassportDir.RetrieveSystemDir() ||
  204. !strPassportDir.PathAppend( PATH_PASSPORT )
  205. )
  206. {
  207. // Could not create CustomError Path
  208. return FALSE;
  209. }
  210. if ( !CSecurityDescriptor::DoesFileSystemSupportACLs(
  211. strPassportDir.QueryStr(),
  212. &bIsAclable ) )
  213. {
  214. return FALSE;
  215. }
  216. if ( !bIsAclable )
  217. {
  218. // Passport dir is not aclable, so lets exit
  219. return TRUE;
  220. }
  221. // If directory does not exist, then create it
  222. if ( !IsFileExist( strPassportDir.QueryStr() ) )
  223. {
  224. if ( !bAdd )
  225. {
  226. // Nothing to remove ACl From
  227. return TRUE;
  228. }
  229. if ( !CreateDirectory( strPassportDir.QueryStr(), NULL ) )
  230. {
  231. // Failed to create passport dir
  232. return FALSE;
  233. }
  234. }
  235. if ( !sdPassport.GetSecurityInfoOnFile( strPassportDir.QueryStr() ) )
  236. {
  237. return FALSE;
  238. }
  239. if ( bAdd )
  240. {
  241. if ( !sdPassport.AddAccessAcebyName( _T("IIS_WPG"),
  242. CSecurityDescriptor::ACCESS_READ_EXECUTE |
  243. CSecurityDescriptor::ACCESS_WRITEONLY |
  244. CSecurityDescriptor::ACCESS_DIR_DELETE,
  245. TRUE,
  246. TRUE )
  247. )
  248. {
  249. return FALSE;
  250. }
  251. }
  252. else
  253. {
  254. if ( !sdPassport.RemoveAccessAcebyName( _T("IIS_WPG") ) )
  255. {
  256. return FALSE;
  257. }
  258. }
  259. if ( !sdPassport.SetSecurityInfoOnFile( strPassportDir.QueryStr(), FALSE ) )
  260. {
  261. // Failed to set ACL
  262. return FALSE;
  263. }
  264. return TRUE;
  265. }
  266. // SetAdminScriptsAcl
  267. //
  268. // Set the ACL on the AdminScripts Directory
  269. //
  270. BOOL
  271. CWebServiceInstallComponent::SetAdminScriptsAcl()
  272. {
  273. TSTR_PATH strAdminScripts;
  274. CSecurityDescriptor AdminSD;
  275. BOOL bDriveIsAclable;
  276. iisDebugOut((LOG_TYPE_PROGRAM_FLOW, _T("Calling SetAdminScriptsAcl\n")));
  277. if ( !strAdminScripts.Copy( g_pTheApp->m_csPathInetpub.GetBuffer(0) ) ||
  278. !strAdminScripts.PathAppend( _T("AdminScripts") ) )
  279. {
  280. // Failed to construct Path
  281. return FALSE;
  282. }
  283. if ( !CSecurityDescriptor::DoesFileSystemSupportACLs(
  284. strAdminScripts.QueryStr(),
  285. &bDriveIsAclable ) )
  286. {
  287. // Failed to check if ACL is valid for this filesystem
  288. return FALSE;
  289. }
  290. if ( !bDriveIsAclable )
  291. {
  292. // This drive is not aclable, so skip it
  293. return TRUE;
  294. }
  295. if ( !AdminSD.AddAccessAcebyWellKnownID( CSecurityDescriptor::GROUP_ADMINISTRATORS,
  296. CSecurityDescriptor::ACCESS_FULL,
  297. TRUE,
  298. TRUE ) ||
  299. !AdminSD.AddAccessAcebyWellKnownID( CSecurityDescriptor::USER_LOCALSYSTEM,
  300. CSecurityDescriptor::ACCESS_FULL,
  301. TRUE,
  302. TRUE ) )
  303. {
  304. // Failed to create Admin SD
  305. return FALSE;
  306. }
  307. if ( !AdminSD.SetSecurityInfoOnFiles( strAdminScripts.QueryStr(), FALSE ) )
  308. {
  309. // Failed to set ACL on this resource
  310. return FALSE;
  311. }
  312. return TRUE;
  313. }
  314. // SetAppropriateFileAcls
  315. //
  316. // To tighten security, set some ACL's in strategic places
  317. // where we install files.
  318. //
  319. // We set the following ACL's on the web root, and
  320. // custom error root
  321. // IUSR_MACHINE: Deny Write and Delete
  322. // IIS_WPG: Allow Read
  323. // Administrators: Allow Full
  324. // Local System: Allow Full
  325. // Users: Allow Read
  326. //
  327. BOOL
  328. CWebServiceInstallComponent::SetAppropriateFileAcls()
  329. {
  330. iisDebugOut((LOG_TYPE_PROGRAM_FLOW, _T("Calling SetAppropriateFileAcls\n")));
  331. return SetAppropriateFileAclsforDrive( _T('*') );
  332. }
  333. // SetAppropriateFileAclsforDrive
  334. //
  335. // Set the appropriate File Acl's, but only for the drive
  336. // specified
  337. //
  338. // Parameters:
  339. // cDriveLetter - The drive letter to be acl'd, send in '*'
  340. // for all drives
  341. //
  342. BOOL
  343. CWebServiceInstallComponent::SetAppropriateFileAclsforDrive( WCHAR cDriveLetter)
  344. {
  345. BOOL bWWWRootIsAclable;
  346. BOOL bCustomErrorsAreAclable;
  347. TSTR_PATH strCustomErrorPath;
  348. iisDebugOut((LOG_TYPE_PROGRAM_FLOW, _T("Calling SetAppropriateFileAclsforDrive\n")));
  349. if ( !strCustomErrorPath.RetrieveWindowsDir() ||
  350. !strCustomErrorPath.PathAppend( PATH_WWW_CUSTOMERRORS )
  351. )
  352. {
  353. // Could not create CustomError Path
  354. return FALSE;
  355. }
  356. if ( !CSecurityDescriptor::DoesFileSystemSupportACLs(
  357. g_pTheApp->m_csPathWWWRoot.GetBuffer(0),
  358. &bWWWRootIsAclable ) ||
  359. !CSecurityDescriptor::DoesFileSystemSupportACLs(
  360. strCustomErrorPath.QueryStr(),
  361. &bCustomErrorsAreAclable ) )
  362. {
  363. // Could not check FS if they were aclable
  364. return FALSE;
  365. }
  366. // Acl everything needed for systemdrive
  367. if ( ( cDriveLetter == _T('*') ) ||
  368. ( tolower( cDriveLetter ) == tolower( *( strCustomErrorPath.QueryStr() ) ) ) )
  369. {
  370. if ( bCustomErrorsAreAclable &&
  371. !SetWWWRootAclonDir( strCustomErrorPath.QueryStr(), FALSE ) )
  372. {
  373. // Failed to set ACL
  374. return FALSE;
  375. }
  376. if ( !SetPassportAcls( TRUE ) )
  377. {
  378. // Failed to set ACL
  379. return FALSE;
  380. }
  381. if ( !SetIISTemporaryDirAcls( TRUE ) )
  382. {
  383. // Failed to set Acl on IIS Temporary Dirs
  384. return FALSE;
  385. }
  386. if ( !SetAdminScriptsAcl() )
  387. {
  388. // Failed to set ACL for AdminScripts directory
  389. return FALSE;
  390. }
  391. }
  392. // Acl everything in inetpub
  393. if ( ( cDriveLetter == _T('*') ) ||
  394. ( tolower( cDriveLetter ) == tolower( *( g_pTheApp->m_csPathWWWRoot.GetBuffer(0) ) ) ) )
  395. {
  396. if ( bWWWRootIsAclable &&
  397. !SetWWWRootAclonDir( g_pTheApp->m_csPathWWWRoot.GetBuffer(0), TRUE ) )
  398. {
  399. // Failed to set ACL
  400. return FALSE;
  401. }
  402. }
  403. return TRUE;
  404. }
  405. // SetIISTemporaryDirAcls
  406. //
  407. // Set the ACL's on the IIS Temporary dirs
  408. //
  409. BOOL
  410. CWebServiceInstallComponent::SetIISTemporaryDirAcls( BOOL bAdd )
  411. {
  412. BOOL bIsAclable;
  413. TSTR_PATH strCompressionDir;
  414. CSecurityDescriptor sdCompression;
  415. iisDebugOut((LOG_TYPE_PROGRAM_FLOW, _T("Calling SetIISTemporaryDirAcls\n")));
  416. if ( !strCompressionDir.RetrieveWindowsDir() ||
  417. !strCompressionDir.PathAppend( PATH_TEMPORARY_COMPRESSION_FILES )
  418. )
  419. {
  420. // Could not create CustomError Path
  421. return FALSE;
  422. }
  423. if ( !CSecurityDescriptor::DoesFileSystemSupportACLs(
  424. strCompressionDir.QueryStr(),
  425. &bIsAclable ) )
  426. {
  427. return FALSE;
  428. }
  429. if ( !bIsAclable )
  430. {
  431. // Passport dir is not aclable, so lets exit
  432. return TRUE;
  433. }
  434. // If directory does not exist, then create it
  435. if ( !IsFileExist( strCompressionDir.QueryStr() ) )
  436. {
  437. if ( !bAdd )
  438. {
  439. // Nothing to remove ACl From
  440. return TRUE;
  441. }
  442. if ( !CreateDirectory( strCompressionDir.QueryStr(), NULL ) )
  443. {
  444. // Failed to create passport dir
  445. return FALSE;
  446. }
  447. }
  448. if ( !sdCompression.GetSecurityInfoOnFile( strCompressionDir.QueryStr() ) )
  449. {
  450. return FALSE;
  451. }
  452. if ( bAdd )
  453. {
  454. if ( !sdCompression.AddAccessAcebyName( _T("IIS_WPG"),
  455. CSecurityDescriptor::ACCESS_FULL,
  456. TRUE,
  457. TRUE )
  458. )
  459. {
  460. return FALSE;
  461. }
  462. }
  463. else
  464. {
  465. if ( !sdCompression.RemoveAccessAcebyName( _T("IIS_WPG") ) )
  466. {
  467. return FALSE;
  468. }
  469. }
  470. if ( !sdCompression.SetSecurityInfoOnFile( strCompressionDir.QueryStr(), FALSE ) )
  471. {
  472. // Failed to set ACL
  473. return FALSE;
  474. }
  475. return TRUE;
  476. }
  477. // SetAspTemporaryDirAcl
  478. //
  479. // Set the ACL's on the ASP Temporary dirs
  480. //
  481. BOOL
  482. CWebServiceInstallComponent::SetAspTemporaryDirAcl( BOOL bAdd )
  483. {
  484. BOOL bIsAclable;
  485. TSTR_PATH strASPDir;
  486. CSecurityDescriptor sdASP;
  487. iisDebugOut((LOG_TYPE_PROGRAM_FLOW, _T("Calling SetAspTemporaryDirAcl\n")));
  488. if ( !strASPDir.RetrieveSystemDir() ||
  489. !strASPDir.PathAppend( PATH_TEMPORARY_ASP_FILES )
  490. )
  491. {
  492. // Could not create CustomError Path
  493. return FALSE;
  494. }
  495. if ( !CSecurityDescriptor::DoesFileSystemSupportACLs(
  496. strASPDir.QueryStr(),
  497. &bIsAclable ) )
  498. {
  499. return FALSE;
  500. }
  501. if ( !bIsAclable )
  502. {
  503. // Passport dir is not aclable, so lets exit
  504. return TRUE;
  505. }
  506. // If directory does not exist, then create it
  507. if ( !IsFileExist( strASPDir.QueryStr() ) )
  508. {
  509. if ( !bAdd )
  510. {
  511. // Nothing to remove ACL From
  512. return TRUE;
  513. }
  514. if ( !CreateDirectory( strASPDir.QueryStr(), NULL ) )
  515. {
  516. // Failed to create ASP Temporary Dir
  517. return FALSE;
  518. }
  519. }
  520. if ( bAdd )
  521. {
  522. if ( !sdASP.AddAccessAcebyName( _T("IIS_WPG"),
  523. CSecurityDescriptor::ACCESS_FULL,
  524. TRUE,
  525. TRUE ) ||
  526. !sdASP.AddAccessAcebyWellKnownID( CSecurityDescriptor::GROUP_ADMINISTRATORS,
  527. CSecurityDescriptor::ACCESS_FULL,
  528. TRUE,
  529. TRUE ) ||
  530. !sdASP.AddAccessAcebyWellKnownID( CSecurityDescriptor::USER_LOCALSYSTEM,
  531. CSecurityDescriptor::ACCESS_FULL,
  532. TRUE,
  533. TRUE )
  534. )
  535. {
  536. // Could not create appropriate ACL
  537. return FALSE;
  538. }
  539. }
  540. else
  541. {
  542. if ( !sdASP.GetSecurityInfoOnFile( strASPDir.QueryStr() ) ||
  543. !sdASP.RemoveAccessAcebyName( _T("IIS_WPG") ) )
  544. {
  545. return FALSE;
  546. }
  547. }
  548. if ( !sdASP.SetSecurityInfoOnFile( strASPDir.QueryStr(), FALSE ) )
  549. {
  550. // Failed to set ACL
  551. return FALSE;
  552. }
  553. return TRUE;
  554. }
  555. // RemoveOurAcls
  556. //
  557. // Remove IIS's Acls from a resource. This is so that when
  558. // we delete the accounts, the bad sid's are not left around
  559. //
  560. BOOL
  561. CWebServiceInstallComponent::RemoveOurAcls( LPTSTR szPhysicalPath)
  562. {
  563. BOOL bIsAclable;
  564. CSecurityDescriptor sd;
  565. iisDebugOut((LOG_TYPE_PROGRAM_FLOW, _T("Calling RemoveOurAcls\n")));
  566. if ( !CSecurityDescriptor::DoesFileSystemSupportACLs(
  567. szPhysicalPath,
  568. &bIsAclable ) )
  569. {
  570. // Failed to check if it was aclable
  571. return FALSE;
  572. }
  573. if ( !bIsAclable )
  574. {
  575. // No acling was needed
  576. return TRUE;
  577. }
  578. if ( !sd.GetSecurityInfoOnFile( szPhysicalPath ) ||
  579. !sd.RemoveAccessAcebyName( g_pTheApp->m_csGuestName.GetBuffer(0), TRUE ) ||
  580. !sd.RemoveAccessAcebyName( _T("IIS_WPG"), TRUE ) ||
  581. !sd.SetSecurityInfoOnFile( szPhysicalPath, FALSE ) )
  582. {
  583. // Failed to remove our acl's
  584. return FALSE;
  585. }
  586. return TRUE;
  587. }
  588. // RemoveAppropriateFileAcls
  589. //
  590. // During install, we explicity set the ACLs for a couple of locations,
  591. // including the \inetpub\wwwroot and the custom errors pages. For uninstall
  592. // we will not remove all the ACL's, since someone might still have
  593. // valuable information in those directories. What we will do, is we will
  594. // remove the ACL's that will not mean anything after we are uninstalled. Like
  595. // the IUSR_ and IIS_WPG since. Since those users are being removed later in setup,
  596. // we must delete the ACL's now.
  597. //
  598. BOOL
  599. CWebServiceInstallComponent::RemoveAppropriateFileAcls()
  600. {
  601. TSTR strCustomErrorPath;
  602. BOOL bRet = TRUE;
  603. iisDebugOut((LOG_TYPE_PROGRAM_FLOW, _T("Calling RemoveAppropriateFileAcls\n")));
  604. if ( !strCustomErrorPath.Copy( g_pTheApp->m_csWinDir ) ||
  605. !strCustomErrorPath.Append( PATH_WWW_CUSTOMERRORS )
  606. )
  607. {
  608. // Could not create CustomError Path
  609. return FALSE;
  610. }
  611. if ( !RemoveOurAcls( g_pTheApp->m_csPathWWWRoot.GetBuffer(0) ) )
  612. {
  613. bRet = FALSE;
  614. }
  615. if ( !RemoveOurAcls( strCustomErrorPath.QueryStr() ) )
  616. {
  617. bRet = FALSE;
  618. }
  619. if ( !SetPassportAcls( FALSE ) )
  620. {
  621. // Failed to set ACL
  622. bRet = FALSE;
  623. }
  624. if ( !SetIISTemporaryDirAcls( FALSE ) )
  625. {
  626. // Failed to set Acl on IIS Temporary Dirs
  627. bRet = FALSE;
  628. }
  629. if ( !SetAspTemporaryDirAcl( FALSE ) )
  630. {
  631. // Failed to remove acl for ASP Temp Dir
  632. bRet = FALSE;
  633. }
  634. return bRet;
  635. }
  636. // SetApplicationDependencies
  637. //
  638. // Set the Application Dependencies as they are defined in the
  639. // unattend file. We take the dependencies from the inf, and
  640. // put them in the metabase
  641. //
  642. BOOL
  643. CWebServiceInstallComponent::SetApplicationDependencies()
  644. {
  645. CApplicationDependencies AppDep;
  646. iisDebugOut((LOG_TYPE_PROGRAM_FLOW, _T("Calling SetApplicationDependencies\n")));
  647. // Load current settings
  648. if ( !AppDep.InitMetabase() ||
  649. !AppDep.LoadCurrentSettings() )
  650. {
  651. return FALSE;
  652. }
  653. // Load Unattend Values
  654. if ( AppDep.DoUnattendSettingsExist() )
  655. {
  656. if ( !AppDep.AddUnattendSettings() )
  657. {
  658. // Failed to add unattend settings
  659. return FALSE;
  660. }
  661. }
  662. if ( !AppDep.AddDefaults() )
  663. {
  664. // Failed to add defaults
  665. return FALSE;
  666. }
  667. return AppDep.SaveSettings();
  668. }
  669. // SetRestrictionList
  670. //
  671. // Set the restriction list for the extensions and CGIs.
  672. //
  673. // This will:
  674. // - Load current RestrictionList
  675. // - Incorporate old values (IsapiRestrictionList and CgiRestrictionList)
  676. // - Load unattend values
  677. // - Add defaults
  678. // - Save them to metabase
  679. //
  680. // Return Values:
  681. // TRUE - Successfully loaded and written
  682. // FALSE - Failure
  683. //
  684. BOOL
  685. CWebServiceInstallComponent::SetRestrictionList()
  686. {
  687. CRestrictionList RestList;
  688. iisDebugOut((LOG_TYPE_PROGRAM_FLOW, _T("Calling SetRestrictionList\n")));
  689. // Load current Value
  690. if ( !RestList.InitMetabase() ||
  691. !RestList.LoadCurrentSettings() )
  692. {
  693. // Failed to load current value
  694. return FALSE;
  695. }
  696. if ( RestList.IsEmpty() &&
  697. IsUpgrade() &&
  698. ( GetUpgradeVersion() == 6 )
  699. )
  700. {
  701. // This is an IIS6 upgrade, so lets try to load the old format
  702. // Isapi and Cgi Restriction Lists
  703. if ( !RestList.ImportOldLists( m_mstrOldCgiRestList,
  704. m_mstrOldIsapiRestList ) )
  705. {
  706. return FALSE;
  707. }
  708. }
  709. // Now lets load values in unattend, if they exist
  710. if ( !RestList.AddUnattendSettings() )
  711. {
  712. return FALSE;
  713. }
  714. // Last, lets put in the default values if they are not already
  715. // present
  716. if ( !RestList.AddDefaults( IsUpgrade() ? TRUE : FALSE ) )
  717. {
  718. return FALSE;
  719. }
  720. // Everything is done, so lets save our new values
  721. return RestList.SaveSettings();
  722. }
  723. // LogWarningonFAT
  724. //
  725. // On Fat systems, just log a warning saying that we are installing on FAT,
  726. // and that is not secure
  727. //
  728. BOOL
  729. CWebServiceInstallComponent::LogWarningonFAT()
  730. {
  731. BOOL bSystemPreservesAcls;
  732. iisDebugOut((LOG_TYPE_PROGRAM_FLOW, _T("Calling LogWarningonFAT\n")));
  733. if ( !DoesTheInstallDrivePreserveAcls( &bSystemPreservesAcls ) )
  734. {
  735. return FALSE;
  736. }
  737. if ( !bSystemPreservesAcls )
  738. {
  739. iisDebugOut((LOG_TYPE_WARN,
  740. _T("IIS is being installed on a fat volume. This will disable IIS security features. Please consider converting the partition from FAT to NTFS.\n") ) );
  741. }
  742. return TRUE;
  743. }
  744. // DisableW3SVCOnUpgrade
  745. //
  746. // Disable W3SVC on Upgrades
  747. // This is determined by checking the registry entry that is set by
  748. // the compatability wizard that runs on the Win2k side of the
  749. // upgrade, and also affected by the unattend setting
  750. //
  751. // Return Values:
  752. // TRUE - Success
  753. // FALSE - Failure
  754. //
  755. BOOL
  756. CWebServiceInstallComponent::DisableW3SVCOnUpgrade()
  757. {
  758. BOOL bDisable = TRUE;
  759. BOOL bRet = TRUE;
  760. CRegValue Value;
  761. CRegistry Registry;
  762. TSTR strUnattendValue( MAX_PATH );
  763. iisDebugOut((LOG_TYPE_PROGRAM_FLOW, _T("Calling DisableW3SVCOnUpgrade\n")));
  764. if ( !Registry.OpenRegistry( HKEY_LOCAL_MACHINE, REG_INETSTP, KEY_READ | KEY_WRITE ) )
  765. {
  766. // Failed to open our node in registry
  767. return FALSE;
  768. }
  769. // Check registry entry
  770. if ( Registry.ReadValue( REGISTR_IISSETUP_DISABLEW3SVC, Value ) )
  771. {
  772. if ( Value.m_dwType == REG_DWORD )
  773. {
  774. // Set Disable to on or off
  775. bDisable = *( (LPDWORD) Value.m_buffData.QueryPtr() ) != 0;
  776. }
  777. // Delete the value, since it is no longer needed
  778. Registry.DeleteValue( REGISTR_IISSETUP_DISABLEW3SVC );
  779. }
  780. if ( ( g_pTheApp->m_hUnattendFile != NULL ) &&
  781. ( g_pTheApp->m_hUnattendFile != INVALID_HANDLE_VALUE) &&
  782. SetupGetLineText( NULL,
  783. g_pTheApp->m_hUnattendFile,
  784. UNATTEND_FILE_SECTION,
  785. UNATTEND_INETSERVER_DISABLEW3SVC,
  786. strUnattendValue.QueryStr(),
  787. strUnattendValue.QuerySize(),
  788. NULL ) )
  789. {
  790. // Retrieved line from unattend, so lets compare
  791. if ( strUnattendValue.IsEqual( _T("true"), FALSE ) )
  792. {
  793. bDisable = TRUE;
  794. }
  795. else if ( strUnattendValue.IsEqual( _T("false"), FALSE ) )
  796. {
  797. bDisable = FALSE;
  798. }
  799. else
  800. {
  801. iisDebugOut((LOG_TYPE_ERROR,
  802. _T("Unattend setting incorrect '%s=%s'\n"),
  803. UNATTEND_INETSERVER_DISABLEW3SVC,
  804. strUnattendValue.QueryStr() ) );
  805. }
  806. }
  807. if ( bDisable )
  808. {
  809. // Disable the W3SVC Service
  810. if ( InetDisableService( _T("W3SVC") ) != 0 )
  811. {
  812. iisDebugOut((LOG_TYPE_ERROR,
  813. _T("Failed to disable W3SVC\n") ) );
  814. bRet = FALSE;
  815. }
  816. g_pTheApp->dwUnattendConfig |= USER_SPECIFIED_INFO_MANUAL_START_WWW;
  817. }
  818. return bRet;
  819. }
  820. // DisableIUSRandIWAMLogons
  821. //
  822. // Disable Terminal Server Logons and RAS VPN Logons
  823. // for both IUSR and IWAM accounts
  824. //
  825. // Return
  826. // TRUE - Successfully changed
  827. // FALSE - Not successfully changed
  828. //
  829. BOOL
  830. CWebServiceInstallComponent::DisableIUSRandIWAMLogons()
  831. {
  832. DWORD dwAllowTSLogin = FALSE;
  833. RAS_USER_1 RasInfo;
  834. iisDebugOut((LOG_TYPE_PROGRAM_FLOW, _T("Calling DisableIUSRandIWAMLogons\n")));
  835. RasInfo.bfPrivilege = RASPRIV_NoCallback | RASPRIV_CallbackType; // No callback
  836. RasInfo.bfPrivilege = 0; // Do not allow dialin
  837. _tcscpy( RasInfo.wszPhoneNumber, _T("") );
  838. // Disable RAS/VPN access for our users
  839. if ( MprAdminUserSetInfo( NULL, // Server
  840. g_pTheApp->m_csWWWAnonyName.GetBuffer(0),
  841. 1, // RAS_USER_0
  842. (LPBYTE) &RasInfo ) != NO_ERROR )
  843. {
  844. return FALSE;
  845. }
  846. if ( MprAdminUserSetInfo( NULL, // Server
  847. g_pTheApp->m_csWAMAccountName.GetBuffer(0),
  848. 1, // RAS_USER_0
  849. (LPBYTE) &RasInfo ) != NO_ERROR )
  850. {
  851. return FALSE;
  852. }
  853. // Disable TS access for our users
  854. // IUSR_ account
  855. if ( !WTSSetUserConfig( WTS_CURRENT_SERVER_NAME,
  856. g_pTheApp->m_csWWWAnonyName.GetBuffer(0),
  857. WTSUserConfigfAllowLogonTerminalServer,
  858. (LPTSTR) &dwAllowTSLogin,
  859. sizeof(DWORD) ) )
  860. {
  861. return FALSE;
  862. }
  863. // IWAM_ account
  864. if ( !WTSSetUserConfig( WTS_CURRENT_SERVER_NAME,
  865. g_pTheApp->m_csWAMAccountName.GetBuffer(0),
  866. WTSUserConfigfAllowLogonTerminalServer,
  867. (LPTSTR) &dwAllowTSLogin,
  868. sizeof(DWORD) ) )
  869. {
  870. return FALSE;
  871. }
  872. return TRUE;
  873. }
  874. // RunMofCompOnIISFiles
  875. //
  876. // Run MofComp on the IIS mofcomp files
  877. //
  878. BOOL
  879. CWebServiceInstallComponent::RunMofCompOnIISFiles()
  880. {
  881. HRESULT hRes;
  882. TSTR_PATH strMofPath;
  883. DWORD dwCurrent;
  884. BOOL bRet = TRUE;
  885. iisDebugOut((LOG_TYPE_PROGRAM_FLOW, _T("Calling RunMofCompOnIISFiles\n")));
  886. if ( m_bMofCompRun )
  887. {
  888. // We have already done this
  889. return TRUE;
  890. }
  891. for ( dwCurrent = 0;
  892. MofCompFiles[ dwCurrent ] != NULL;
  893. dwCurrent++ )
  894. {
  895. if ( !strMofPath.Copy( g_pTheApp->m_csPathInetsrv.GetBuffer(0) ) ||
  896. !strMofPath.PathAppend( MofCompFiles[ dwCurrent ] ) )
  897. {
  898. // Fatal Error
  899. iisDebugOut((LOG_TYPE_ERROR,
  900. _T("RunMofCompOnIISFiles: Failed to construct path for '%s'\n"),
  901. MofCompFiles[ dwCurrent ] ) );
  902. return FALSE;
  903. }
  904. hRes = MofCompile( strMofPath.QueryStr() );
  905. if ( FAILED( hRes ) )
  906. {
  907. iisDebugOut((LOG_TYPE_ERROR,
  908. _T("RunMofCompOnIISFiles: Failed to mofcomp on file '%s', hRes=0x%8x\n"),
  909. strMofPath.QueryStr(),
  910. hRes ) );
  911. bRet = FALSE;
  912. }
  913. }
  914. if ( bRet )
  915. {
  916. m_bMofCompRun = TRUE;
  917. }
  918. return bRet;
  919. }
  920. // CheckIfWebDavIsDisabled
  921. //
  922. // Check if WebDav is disabled via the IIS Lockdown tool for
  923. // IIS 4, 5, and 5.1
  924. //
  925. BOOL
  926. CWebServiceInstallComponent::CheckIfWebDavIsDisabled()
  927. {
  928. BOOL bIsAclDisabled;
  929. BOOL bIsRegistryDisabled = FALSE;
  930. CRegValue Value;
  931. CRegistry Registry;
  932. iisDebugOut((LOG_TYPE_PROGRAM_FLOW, _T("Calling CheckIfWebDavIsDisabled\n")));
  933. if ( !IsUpgrade() ||
  934. ( GetUpgradeVersion() <= 3 ) ||
  935. ( GetUpgradeVersion() >= 6 ) )
  936. {
  937. // Since we either not upgrading, or the version is not between
  938. // 4 and 5.1, lets not do the test
  939. return TRUE;
  940. }
  941. if ( !IsWebDavDisabled( &bIsAclDisabled ) ||
  942. !IsWebDavDisabledViaRegistry( &bIsRegistryDisabled ) )
  943. {
  944. // Failed during check
  945. return FALSE;
  946. }
  947. m_bWebDavIsDisabled = bIsAclDisabled || bIsRegistryDisabled;
  948. return TRUE;
  949. }
  950. // DisabledWebDavOnUpgrade
  951. //
  952. // If Web DAV was disabled before the upgrade via acl's, then lets
  953. // put that in the restriction list now
  954. //
  955. BOOL
  956. CWebServiceInstallComponent::DisabledWebDavOnUpgrade()
  957. {
  958. iisDebugOut((LOG_TYPE_PROGRAM_FLOW, _T("Calling DisabledWebDavOnUpgrade\n")));
  959. if ( !m_bWebDavIsDisabled )
  960. {
  961. // Nothing needed to be done
  962. return TRUE;
  963. }
  964. return DisableWebDavInRestrictionList();
  965. }
  966. // SetServiceToManualIfNeeded
  967. //
  968. // Set the service to manual if specified in unattend file
  969. //
  970. BOOL
  971. CWebServiceInstallComponent::SetServiceToManualIfNeeded()
  972. {
  973. iisDebugOut((LOG_TYPE_PROGRAM_FLOW, _T("Calling SetServiceToManualIfNeeded\n")));
  974. if ( g_pTheApp->dwUnattendConfig & USER_SPECIFIED_INFO_MANUAL_START_WWW )
  975. {
  976. SetServiceStart( _T("W3SVC"), SERVICE_DEMAND_START );
  977. }
  978. return TRUE;
  979. }
  980. // PreInstall
  981. //
  982. // Do all of the work that needs to be done before we do
  983. // all the heavy install work
  984. //
  985. BOOL
  986. CWebServiceInstallComponent::PreInstall()
  987. {
  988. BOOL bRet = TRUE;
  989. iisDebugOut((LOG_TYPE_PROGRAM_FLOW, _T("Calling PreInstall\n")));
  990. // Rename the "Web Applications" group to IIS_WPG. This group is created by IIS Lockdown tool
  991. if ( bRet && IsUpgrade() && ( GetUpgradeVersion() >= 4 ) )
  992. {
  993. if ( LocalGroupExists( OLD_WAM_GROUPNAME ) )
  994. {
  995. if ( !LocalGroupExists( IIS_WPG_GROUPNAME ) )
  996. {
  997. LOCALGROUP_INFO_0 Info = { const_cast<LPWSTR>( IIS_WPG_GROUPNAME ) };
  998. if ( ::NetLocalGroupSetInfo( NULL, OLD_WAM_GROUPNAME, 0, (BYTE*)&Info, NULL ) != NERR_Success )
  999. {
  1000. iisDebugOut((LOG_TYPE_ERROR, _T("Failed to rename '%s' group to '%s'!\n"), OLD_WAM_GROUPNAME, IIS_WPG_GROUPNAME ));
  1001. bRet = FALSE;
  1002. }
  1003. }
  1004. else
  1005. {
  1006. // IIS_WPG NT group should not exist at this point. If it does - move the code that creates it
  1007. // later or do no create it if the 'Web Applications' group exist
  1008. _ASSERT( false );
  1009. iisDebugOut((LOG_TYPE_ERROR, _T("IIS_WPG group exists. Cannot rename 'Web Applications'!\n"), OLD_WAM_GROUPNAME, IIS_WPG_GROUPNAME ));
  1010. }
  1011. }
  1012. }
  1013. bRet = bRet && CheckIfWebDavIsDisabled();
  1014. if ( bRet && IsUpgrade() )
  1015. {
  1016. if ( GetUpgradeVersion() == 6 )
  1017. {
  1018. // If it is an IIS6 upgrade, then we should load the old Cgi and Isapi Restriction
  1019. // Lists, because the metabase no longer know anything about them
  1020. bRet = bRet && CRestrictionList::LoadOldFormatSettings( &m_mstrOldCgiRestList,
  1021. &m_mstrOldIsapiRestList );
  1022. }
  1023. }
  1024. return bRet;
  1025. }
  1026. // Install
  1027. //
  1028. // Do all of the main work need for install
  1029. //
  1030. BOOL
  1031. CWebServiceInstallComponent::Install()
  1032. {
  1033. BOOL bRet = TRUE;
  1034. iisDebugOut((LOG_TYPE_PROGRAM_FLOW, _T("Executing Install of WWW Component...\n")));
  1035. bRet = bRet && SetVersionInMetabase();
  1036. bRet = bRet && SetAppropriateFileAcls();
  1037. /*bRet = bRet &&*/ DisableIUSRandIWAMLogons();
  1038. // Load the Restriction List and Application Dependencies
  1039. bRet = bRet && DisabledWebDavOnUpgrade();
  1040. bRet = bRet && SetRestrictionList();
  1041. bRet = bRet && SetApplicationDependencies();
  1042. bRet = bRet && SetServiceToManualIfNeeded();
  1043. bRet = bRet && AddInheritFlagToSSLUseDSMap();
  1044. bRet = bRet && SetRegEntries( TRUE );
  1045. bRet = bRet && UpdateSiteFiltersAcl(); // Set /w3svc/X/filters acl
  1046. if ( IsUpgrade() )
  1047. {
  1048. //Do work for upgrades
  1049. bRet = bRet && ProcessIISShims(); // Import IIS Shims from the AppCompat sys DB
  1050. bRet = bRet && UpgradeRestrictedExtensions(); // Upgrade restricted ( 404.dall mapped ) extension to WebSvcExtRestrictionList
  1051. if ( ( GetUpgradeVersion() >= 4 ) &&
  1052. ( GetUpgradeVersion() < 6 ) )
  1053. {
  1054. bRet = bRet && UpgradeWAMUsers();
  1055. }
  1056. if ( GetUpgradeVersion() == 5 )
  1057. {
  1058. // Do work for Win2k Upgrades
  1059. bRet = bRet && DisableW3SVCOnUpgrade();
  1060. }
  1061. if ( ( GetUpgradeVersion() >= 4 ) &&
  1062. ( GetUpgradeVersion() <= 5 ) )
  1063. {
  1064. // Remove IIS Help Vdir
  1065. bRet = bRet && RemoveHelpVdironUpgrade();
  1066. }
  1067. }
  1068. if ( !g_pTheApp->m_fNTGuiMode )
  1069. {
  1070. // Do non GUI stuff
  1071. bRet = bRet && RunMofCompOnIISFiles(); // If in GUI, must do at OC_CLEANUP
  1072. }
  1073. bRet = bRet && LogWarningonFAT();
  1074. return bRet;
  1075. }
  1076. // Post install
  1077. //
  1078. BOOL
  1079. CWebServiceInstallComponent::PostInstall()
  1080. {
  1081. BOOL bRet = TRUE;
  1082. iisDebugOut((LOG_TYPE_PROGRAM_FLOW, _T("Executing PostInstall for the WWW component...\n")));
  1083. // Run MofComp if not already run
  1084. bRet = bRet && RunMofCompOnIISFiles();
  1085. bRet = bRet && InitialMetabaseBackUp( TRUE ); // Backup Metabase
  1086. // Start the service
  1087. if ( !g_pTheApp->m_fNTGuiMode &&
  1088. ( g_pTheApp->dwUnattendConfig & USER_SPECIFIED_INFO_MANUAL_START_WWW ) == 0 )
  1089. {
  1090. // If it is not GUI mode, then we will try an start the service.
  1091. // It's not fatal if we fail to start the service, but return result anyway
  1092. INT nRes = InetStartService( _T("W3SVC") );
  1093. bRet = ( (nRes == ERROR_SUCCESS) || (nRes == ERROR_SERVICE_ALREADY_RUNNING) );
  1094. }
  1095. return bRet;
  1096. }
  1097. // Uninstall
  1098. //
  1099. // Do all the main work to uninstall the component
  1100. //
  1101. BOOL
  1102. CWebServiceInstallComponent::UnInstall()
  1103. {
  1104. BOOL bRet = TRUE;
  1105. iisDebugOut((LOG_TYPE_PROGRAM_FLOW, _T("Executing UnInstall of WWW Component...\n")));
  1106. bRet = SetRegEntries( FALSE ) && bRet;
  1107. bRet = InitialMetabaseBackUp( FALSE ) && bRet;
  1108. return bRet;
  1109. }
  1110. // PreUninstall
  1111. //
  1112. // Do everything that needs to be done before uninstall
  1113. //
  1114. BOOL
  1115. CWebServiceInstallComponent::PreUnInstall()
  1116. {
  1117. BOOL bRet = TRUE;
  1118. iisDebugOut((LOG_TYPE_PROGRAM_FLOW, _T("Executing PreUnInstall of WWW Component...\n")));
  1119. bRet = bRet && RemoveAppropriateFileAcls();
  1120. return bRet;
  1121. }
  1122. /*
  1123. Locates all MD_WAM_USER_NAME values in the metabse and inserts each value ( the value is NT username )
  1124. in the IIS_WPG NT Group
  1125. */
  1126. BOOL CWebServiceInstallComponent::UpgradeWAMUsers()
  1127. {
  1128. iisDebugOut((LOG_TYPE_PROGRAM_FLOW, _T("Upgrading WAM users...\n")));
  1129. // We support only UNICODE now. This functions is designed for UNICODE only!
  1130. #if !( defined(UNICODE) || defined(_UNICODE) )
  1131. #error UNICODE build required
  1132. #endif
  1133. // Find all nodes that have MD_WAM_USER_NAME explicitly set
  1134. CMDKey MBKey;
  1135. CStringList listPaths;
  1136. if ( FAILED( MBKey.OpenNode( METABASEPATH_WWW_ROOT ) ) )
  1137. {
  1138. iisDebugOut((LOG_TYPE_ERROR, _T("Failed open LM/W3SVC node\n") ));
  1139. return FALSE;
  1140. }
  1141. if ( FAILED( MBKey.GetDataPaths( MD_WAM_USER_NAME, STRING_METADATA, /*r*/listPaths ) ) )
  1142. {
  1143. iisDebugOut((LOG_TYPE_ERROR, _T("Failed to get data paths from LM/W3SVC node\n") ));
  1144. return FALSE;
  1145. }
  1146. // Get each value
  1147. POSITION pos = listPaths.GetHeadPosition();
  1148. BOOL bRet = TRUE;
  1149. while( pos != NULL )
  1150. {
  1151. CString strPath = listPaths.GetNext( pos );
  1152. CMDValue UserName;
  1153. BOOL bResult = MBKey.GetData( /*r*/UserName, MD_WAM_USER_NAME, strPath.GetBuffer( 0 ) );
  1154. if ( bResult )
  1155. {
  1156. NET_API_STATUS nRes = RegisterAccountToLocalGroup( reinterpret_cast<LPCWSTR>( UserName.GetData() ),
  1157. IIS_WPG_GROUPNAME,
  1158. TRUE );
  1159. bResult = ( ( nRes == NERR_Success ) || ( nRes == ERROR_MEMBER_IN_ALIAS ) );
  1160. }
  1161. if ( !bResult )
  1162. {
  1163. // Log error but try to import the other usernames
  1164. iisDebugOut((LOG_TYPE_ERROR, _T("Failed to transfer a WAM user from MB to IIS_WPG. Will try with next one...\n") ));
  1165. bRet = FALSE;
  1166. }
  1167. };
  1168. return bRet;
  1169. }
  1170. /*
  1171. Get all script maps ( on each level bellow LM/W3SVC )
  1172. For each script mapping - if there is a disabled extension - restore the mapping to the original one
  1173. and create a disabled entry for this extension in the WebSvcExtRestrictionList
  1174. */
  1175. BOOL CWebServiceInstallComponent::UpgradeRestrictedExtensions()
  1176. {
  1177. typedef std::map<std::wstring, DWORD> TExtMap;
  1178. typedef std::list<std::pair<std::wstring, std::wstring> > TStrStrList;
  1179. // This shows whether a particular ext group ( an elem of TExtToCheck ) should be upgraded
  1180. enum GroupState
  1181. {
  1182. esUnknown, // Don't know if the element should be upgraded, so it woun't be
  1183. esUpgrade, // Upgrade it ( move it to WebSvcExtRestrictionList
  1184. esDontUpgrade // No thanks
  1185. };
  1186. // This is the array that flags which extensions should be moved to WebSvcExtRe...
  1187. GroupState anUpgradeExt[ TExtToCheck::ARRAY_SIZE ];
  1188. // Create a map for the file extension that we need to check
  1189. // The map is Extension->ExtnesionIndex
  1190. // Where Extension is the filename extension ( ".asp" )
  1191. // And ExtensionIndex is the array index in TExtToCheck and abUpgradeExt
  1192. TExtMap mapExt;
  1193. // This list holds a pair of strings. The first one is the full MB key where a script map is located
  1194. // The second script is extension name ( ".asp" )
  1195. // At one point of time we will change the mapping of this extension to be the default filename
  1196. TStrStrList listKeysToUpdate;
  1197. // Create the map with the extensions
  1198. // By default no extensions will be upgraded ( which means - added as disabled in WebSvcExtRestrictionList )
  1199. for ( DWORD iExtInfo = 0; iExtInfo < TExtToCheck::ARRAY_SIZE; ++iExtInfo )
  1200. {
  1201. anUpgradeExt[ iExtInfo ] = esUnknown;
  1202. // Enter the extensions in the map
  1203. for ( DWORD iExt = 0; iExt < sOurDefaultExtensions::MaxFileExtCount; ++iExt )
  1204. {
  1205. if ( TExtToCheck::Element( iExtInfo ).szExtensions[ iExt ] != NULL )
  1206. {
  1207. // Put this extension in the map
  1208. TExtMap::value_type New( std::wstring( TExtToCheck::Element( iExtInfo ).szExtensions[ iExt ] ), iExtInfo );
  1209. mapExt.insert( New );
  1210. }
  1211. }
  1212. }
  1213. // Get all paths at which the script mappings are set
  1214. CStringList listPaths;
  1215. CMDKey mdKey;
  1216. if ( FAILED( mdKey.OpenNode( METABASEPATH_WWW_ROOT ) ) ) return FALSE;
  1217. if ( FAILED( mdKey.GetDataPaths( MD_SCRIPT_MAPS, MULTISZ_METADATA, /*r*/listPaths ) ) ) return FALSE;
  1218. POSITION pos = listPaths.GetHeadPosition();
  1219. // For each script map - check if every mapping in the map is mapped to 404.dll
  1220. // and if so - whether this is an IIS extension
  1221. while( pos != NULL )
  1222. {
  1223. const CString strSubPath = listPaths.GetNext( /*r*/pos );
  1224. DWORD dwType = 0;
  1225. DWORD dwAttribs = 0;
  1226. LPCWSTR wszSubKey = strSubPath;
  1227. CStringList listMappings;
  1228. // If we fail - exit. No need to continue with other paths because we
  1229. // need to be sure that no mapping exist to anything different then 404.dll
  1230. if ( FAILED( mdKey.GetMultiSzAsStringList( MD_SCRIPT_MAPS,
  1231. &dwType,
  1232. &dwAttribs,
  1233. /*r*/listMappings,
  1234. wszSubKey ) ) )
  1235. {
  1236. iisDebugOut((LOG_TYPE_ERROR, _T("Failed to get and parse ScriptMap value\n") ));
  1237. return FALSE;
  1238. }
  1239. // For each mapping in the script map - get what ext is mapped to what filename
  1240. // If it is one of our extensions ( the ones in the map ) - check the filename
  1241. // If the filename is not 404.dll - this extension will not be modified
  1242. POSITION posMapping = listMappings.GetHeadPosition();
  1243. while( posMapping != NULL )
  1244. {
  1245. WCHAR wszFilename[ MAX_PATH ];
  1246. CString strMapping = listMappings.GetNext( /*r*/posMapping );
  1247. LPCWSTR wszMapping = strMapping;
  1248. LPCWSTR wszFirstComma = ::wcschr( wszMapping, L',' ) + 1; // Will point at the first symb after the comma
  1249. if ( NULL == wszFirstComma )
  1250. {
  1251. iisDebugOut((LOG_TYPE_ERROR, _T("Invalid mapping: %s\n"),wszMapping ));
  1252. return FALSE;
  1253. }
  1254. LPCWSTR wszSecondComma = ::wcschr( wszFirstComma, L',' ); // Will point at the second comma
  1255. if ( NULL == wszSecondComma )
  1256. {
  1257. // Set to point at the end of the string
  1258. wszSecondComma = wszMapping + ::wcslen( wszMapping );
  1259. }
  1260. // Get the extension and the filename
  1261. ::wcsncpy( wszFilename, wszFirstComma, min( wszSecondComma - wszFirstComma, MAX_PATH ) );
  1262. wszFilename[ min( wszSecondComma - wszFirstComma, MAX_PATH ) ] = L'\0';
  1263. std::wstring strExt( wszMapping, wszFirstComma - wszMapping - 1 ); // -1 to remove the comma as well
  1264. TExtMap::iterator it = mapExt.find( strExt );
  1265. // If this is not an IIS extension - skip it
  1266. if ( mapExt.end() == it ) continue;
  1267. // Strip the path to be the filename only
  1268. ::PathStripPath( wszFilename );
  1269. if ( ::_wcsicmp( wszFilename, L"404.dll" ) != 0 )
  1270. {
  1271. // If this is not an 404.dll filename - this extension will not be upgraded
  1272. anUpgradeExt[ it->second ] = esDontUpgrade;
  1273. }
  1274. else
  1275. {
  1276. // This is an IIS ext mapped to 404.dll.
  1277. // If this group upgrade flag is not esDontUpgrade - then we will upgrade the group
  1278. if ( anUpgradeExt[ it->second ] != esDontUpgrade )
  1279. {
  1280. anUpgradeExt[ it->second ] = esUpgrade;
  1281. // We may need to upgrade this entry, so store it
  1282. std::wstring strKeyName( L"LM/W3SVC/" );
  1283. strKeyName += ( L'/' == wszSubKey[ 0 ] ) ? wszSubKey + 1 : wszSubKey;
  1284. listKeysToUpdate.push_back( TStrStrList::value_type( strKeyName, strExt ) );
  1285. }
  1286. }
  1287. };
  1288. };
  1289. // Close the MB key. It is important to close it here because we will write to LM/W3SVC node
  1290. // so we should not have open handles
  1291. mdKey.Close();
  1292. // Right here, in anUpgradeExt we have esUpgrade values for all WebSvcExtensions we need to upgrade
  1293. // In listKeysToUpdate we have all the keys that contains script maps that contain
  1294. // mappings that MAY need to be modified. So perform the upgrade now
  1295. // Modify the script mappings for file extensions that will be upgraded
  1296. for ( TStrStrList::iterator itMapping = listKeysToUpdate.begin();
  1297. itMapping != listKeysToUpdate.end();
  1298. ++itMapping )
  1299. {
  1300. // Find which element in TExtToCheck array represents this extension
  1301. TExtMap::iterator itInfo = mapExt.find( itMapping->second.c_str() );
  1302. // For an extension to be in listKeysToUpdate, it should've existed in mapExt.
  1303. // So we will always find it
  1304. _ASSERT( itInfo != mapExt.end() );
  1305. // If we will upgrade this extension info - then we need to modify this value
  1306. if ( esUpgrade == anUpgradeExt[ itInfo->second ] )
  1307. {
  1308. // Don't fail on error - try to update as many mappings as possible
  1309. if ( !UpdateScriptMapping( itMapping->first.c_str(), itMapping->second.c_str(), itInfo->second ) )
  1310. {
  1311. iisDebugOut(( LOG_TYPE_ERROR,
  1312. _T("Failed to update script mapping. Ext='%s' at '%s'\n"),
  1313. itMapping->second.c_str(),
  1314. itMapping->first.c_str() ));
  1315. }
  1316. }
  1317. }
  1318. CSecConLib Helper;
  1319. TSTR_PATH strFullPath( MAX_PATH );
  1320. BOOL bRet = TRUE;
  1321. // Now we need to put an entry in WebSvcExtRestrictionList for all disabled ISAPI dlls
  1322. // The ones we need to process are the ones on abUpgradeExt for which the element is TRUE
  1323. for ( DWORD iExtInfo = 0; iExtInfo < TExtToCheck::ARRAY_SIZE; ++iExtInfo )
  1324. {
  1325. if ( esUpgrade == anUpgradeExt[ iExtInfo ] )
  1326. {
  1327. TSTR strDesc;
  1328. // Extensions from the first array go to InetSrv dir
  1329. // Extensions from the second array - System32
  1330. LPCWSTR wszDir = TExtToCheck::IsIndexInFirst( iExtInfo ) ?
  1331. g_pTheApp->m_csPathInetsrv.GetBuffer(0) :
  1332. g_pTheApp->m_csSysDir.GetBuffer(0);
  1333. if ( !strFullPath.Copy( wszDir ) ||
  1334. !strFullPath.PathAppend( TExtToCheck::Element( iExtInfo ).szFileName ) ||
  1335. !strDesc.LoadString( TExtToCheck::Element( iExtInfo ).dwProductName ) )
  1336. {
  1337. // Failed to create full path, so skip to next one
  1338. bRet = FALSE;
  1339. iisDebugOut((LOG_TYPE_ERROR, _T("Unable to build full path for WebSvc extension. Possible OutOfMem\n") ));
  1340. continue;
  1341. }
  1342. // Delete the extension first ( the SeccLib will fail to add an extension if it's alreafy there )
  1343. HRESULT hrDel = Helper.DeleteExtensionFileRecord( strFullPath.QueryStr(), METABASEPATH_WWW_ROOT );
  1344. if ( FAILED( hrDel ) && ( hrDel != MD_ERROR_DATA_NOT_FOUND ) )
  1345. {
  1346. iisDebugOut(( LOG_TYPE_WARN,
  1347. _T("Failed to delete extension file '%s' in order to change it's settings\n"),
  1348. strFullPath.QueryStr() ) );
  1349. bRet = FALSE;
  1350. continue;
  1351. }
  1352. if ( FAILED( Helper.AddExtensionFile( strFullPath.QueryStr(), // Path
  1353. false, // Image should be disabled
  1354. TExtToCheck::Element( iExtInfo ).szNotLocalizedGroupName, // GroupID
  1355. TExtToCheck::Element( iExtInfo ).bUIDeletable != FALSE, // UI deletable
  1356. strDesc.QueryStr(), // Group description
  1357. METABASEPATH_WWW_ROOT ) ) ) // MB location
  1358. {
  1359. iisDebugOut(( LOG_TYPE_WARN,
  1360. _T("Failed to add extension '%s' to group '%s'\n"),
  1361. strFullPath.QueryStr(),
  1362. TExtToCheck::Element( iExtInfo ).szNotLocalizedGroupName ));
  1363. bRet = FALSE;
  1364. continue;
  1365. }
  1366. }
  1367. }
  1368. return bRet;
  1369. }
  1370. /*
  1371. This function updates the script mapping value ( MD_SCRIPT_MAP ) under the
  1372. metabase key wszMBKey.
  1373. The file extension wszExt will be associated with the filename specified in TExtToCheck[ iExtInfo ]
  1374. */
  1375. BOOL CWebServiceInstallComponent::UpdateScriptMapping( LPCWSTR wszMBKey, LPCWSTR wszExt, DWORD iExtInfo )
  1376. {
  1377. _ASSERT( wszMBKey != NULL );
  1378. _ASSERT( ::wcsstr( wszMBKey, L"LM/W3SVC" ) != NULL );
  1379. _ASSERT( wszExt != NULL );
  1380. _ASSERT( iExtInfo < TExtToCheck::ARRAY_SIZE );
  1381. CMDKey Key;
  1382. CStringList listMappings;
  1383. DWORD dwType = 0;
  1384. DWORD dwAttribs = 0;
  1385. if ( FAILED( Key.OpenNode( wszMBKey ) ) ) return FALSE;
  1386. if ( FAILED( Key.GetMultiSzAsStringList( MD_SCRIPT_MAPS, &dwType, &dwAttribs, /*r*/listMappings ) ) ) return FALSE;
  1387. // Find the string that is the extension we are looking for
  1388. POSITION pos = listMappings.GetHeadPosition();
  1389. while( pos != NULL )
  1390. {
  1391. CString strMapping = listMappings.GetAt( pos );
  1392. // The mapping must be large enough to consist of our ext, +2 symbols for the first and second commas
  1393. // and +1 for at least one symbol for filename
  1394. if ( static_cast<size_t>( strMapping.GetLength() ) <= ( ::wcslen( wszExt ) + 2 + 1 ) )
  1395. {
  1396. continue;
  1397. }
  1398. // Check if this is the exteniosn we are looking for
  1399. if ( ::_wcsnicmp( wszExt, strMapping, ::wcslen( wszExt ) ) == 0 )
  1400. {
  1401. // Create the full path to the ISAPI that this ext should be mapped to
  1402. TSTR_PATH strFullPath( MAX_PATH );
  1403. // There is a little trick here - extensions from the first array go to InetSrv dir
  1404. // Extensions from the second array - System32
  1405. LPCWSTR wszDir = TExtToCheck::IsIndexInFirst( iExtInfo ) ?
  1406. g_pTheApp->m_csPathInetsrv.GetBuffer(0) :
  1407. g_pTheApp->m_csSysDir.GetBuffer(0);
  1408. if ( !strFullPath.Copy( wszDir ) ||
  1409. !strFullPath.PathAppend( TExtToCheck::Element( iExtInfo ).szFileName ) )
  1410. {
  1411. iisDebugOut((LOG_TYPE_ERROR, _T("Unable to build full path for WebSvc extension. Possible OutOfMem\n") ));
  1412. return FALSE;
  1413. }
  1414. LPCWSTR wszMapping = strMapping;
  1415. LPCWSTR wszTheRest = ::wcschr( wszMapping + wcslen( wszExt ) + 1, L',' );
  1416. _ASSERT( wszTheRest != NULL );
  1417. // Our buffer will be the ext size, +1 comma, +Path, + the rest of it +1 for the '\0'
  1418. std::auto_ptr<WCHAR> spMapping( new WCHAR[ ::wcslen( wszExt ) + 1 + strFullPath.QueryLen() + ::wcslen( wszTheRest ) + 1 ] );
  1419. if ( NULL == spMapping.get() ) return FALSE;
  1420. ::wcscpy( spMapping.get(), wszExt );
  1421. ::wcscat( spMapping.get(), L"," );
  1422. ::wcscat( spMapping.get(), strFullPath.QueryStr() );
  1423. ::wcscat( spMapping.get(), wszTheRest );
  1424. listMappings.SetAt( pos, CString( spMapping.get() ) );
  1425. if ( FAILED( Key.SetMultiSzAsStringList( MD_SCRIPT_MAPS, dwType, dwAttribs, listMappings ) ) )
  1426. {
  1427. iisDebugOut(( LOG_TYPE_ERROR,
  1428. _T("Failed to modify extension mapping ( ISAPI dll name ) for ext '%s' in '%s'\n"),
  1429. wszExt,
  1430. wszMBKey ));
  1431. }
  1432. // Thats it
  1433. break;
  1434. }
  1435. listMappings.GetNext( /*r*/pos );
  1436. }
  1437. return TRUE;
  1438. }
  1439. // SetVersionInMetabase
  1440. //
  1441. // Set the version information in the metabase
  1442. //
  1443. // Return Values
  1444. // TRUE - Successfully Set
  1445. // FALSE - Failed to Set
  1446. //
  1447. BOOL
  1448. CWebServiceInstallComponent::SetVersionInMetabase()
  1449. {
  1450. CMDValue MajorVersion;
  1451. CMDValue MinorVersion;
  1452. CMDKey Metabase;
  1453. iisDebugOut((LOG_TYPE_PROGRAM_FLOW, _T("Calling SetVersionInMetabase\n")));
  1454. if ( !MajorVersion.SetValue( MD_SERVER_VERSION_MAJOR,
  1455. 0,
  1456. DWORD_METADATA,
  1457. IIS_SERVER_VERSION_MAJOR ) ||
  1458. !MinorVersion.SetValue( MD_SERVER_VERSION_MINOR,
  1459. 0,
  1460. DWORD_METADATA,
  1461. IIS_SERVER_VERSION_MINOR ) )
  1462. {
  1463. // Could not create properties
  1464. return FALSE;
  1465. }
  1466. if ( FAILED( Metabase.OpenNode( METABASEPATH_WWW_INFO ) ) ||
  1467. !Metabase.SetData( MajorVersion, MD_SERVER_VERSION_MAJOR ) ||
  1468. !Metabase.SetData( MinorVersion, MD_SERVER_VERSION_MINOR ) )
  1469. {
  1470. // Failed to set
  1471. return FALSE;
  1472. }
  1473. return TRUE;
  1474. }
  1475. // RemoveIISHelpVdir
  1476. //
  1477. // Remove an IISHelp Vdir, if it exists
  1478. //
  1479. // Parameters
  1480. // szMetabasePath - Metabase path of website
  1481. // szPhysicalPath1 - One of the physical path's it could point to, to be considered valid
  1482. // szPhysicalPath1 - The second possible physical path it could point to, to be considered valid
  1483. //
  1484. BOOL
  1485. CWebServiceInstallComponent::RemoveIISHelpVdir( LPCTSTR szMetabasePath, LPCTSTR szPhysicalPath1, LPCTSTR szPhysicalPath2 )
  1486. {
  1487. CMDKey cmdKey;
  1488. CMDValue cmdValue;
  1489. TSTR strFullPath;
  1490. iisDebugOut((LOG_TYPE_PROGRAM_FLOW, _T("Calling RemoveIISHelpVdir\n")));
  1491. if ( !strFullPath.Copy( szMetabasePath ) ||
  1492. !strFullPath.Append( _T("/") ) ||
  1493. !strFullPath.Append( METABASEPATH_UPG_IISHELP_NAME ) )
  1494. {
  1495. // Failed to construct Full Path
  1496. return FALSE;
  1497. }
  1498. if ( SUCCEEDED( cmdKey.OpenNode( strFullPath.QueryStr() ) ) &&
  1499. cmdKey.GetData( cmdValue, MD_VR_PATH ) &&
  1500. ( cmdValue.GetDataType() == STRING_METADATA ) &&
  1501. ( ( _tcsicmp( (LPTSTR) cmdValue.GetData(), szPhysicalPath1 ) == 0 ) ||
  1502. ( _tcsicmp( (LPTSTR) cmdValue.GetData(), szPhysicalPath2 ) == 0 )
  1503. )
  1504. )
  1505. {
  1506. cmdKey.Close();
  1507. // This is the correct vdir, so lets delete it
  1508. if ( FAILED( cmdKey.OpenNode( szMetabasePath ) ) )
  1509. {
  1510. // Failed to open node
  1511. return FALSE;
  1512. }
  1513. if ( FAILED( cmdKey.DeleteNode( METABASEPATH_UPG_IISHELP_NAME ) ) )
  1514. {
  1515. // Failed to remove vdir
  1516. return FALSE;
  1517. }
  1518. }
  1519. return TRUE;
  1520. }
  1521. // RemoveHelpVdironUpgrade
  1522. //
  1523. // Remove the IIS Help vdir on upgrades
  1524. //
  1525. BOOL
  1526. CWebServiceInstallComponent::RemoveHelpVdironUpgrade()
  1527. {
  1528. TSTR_PATH strHelpLoc1;
  1529. TSTR_PATH strHelpLoc2;
  1530. TSTR_PATH strHelpDeleteLoc;
  1531. iisDebugOut((LOG_TYPE_PROGRAM_FLOW, _T("Calling RemoveHelpVdironUpgrade\n")));
  1532. if ( !strHelpLoc1.RetrieveWindowsDir() ||
  1533. !strHelpLoc1.PathAppend( PATH_UPG_IISHELP_1 ) ||
  1534. !strHelpLoc2.RetrieveWindowsDir() ||
  1535. !strHelpLoc2.PathAppend( PATH_UPG_IISHELP_2 ) ||
  1536. !strHelpDeleteLoc.RetrieveWindowsDir() ||
  1537. !strHelpDeleteLoc.PathAppend( PATH_IISHELP_DEL ) )
  1538. {
  1539. // Failed to create Path
  1540. return FALSE;
  1541. }
  1542. if ( !RemoveIISHelpVdir( METABASEPATH_UPG_IISHELP_WEB1_ROOT,
  1543. strHelpLoc1.QueryStr(),
  1544. strHelpLoc2.QueryStr() ) ||
  1545. !RemoveIISHelpVdir( METABASEPATH_UPG_IISHELP_WEB2_ROOT,
  1546. strHelpLoc1.QueryStr(),
  1547. strHelpLoc2.QueryStr() ) )
  1548. {
  1549. // Failed to remove VDir
  1550. return FALSE;
  1551. }
  1552. // Now delete directory
  1553. RecRemoveDir( strHelpDeleteLoc.QueryStr(), TRUE );
  1554. return TRUE;
  1555. }
  1556. // CreateInitialMetabaseBackUp
  1557. //
  1558. // Create an initial backup of the metabase at the end of
  1559. // the W3SVC Instalation
  1560. //
  1561. // Parameters:
  1562. // bAdd - TRUE == Add,
  1563. // FALSE == remove
  1564. //
  1565. BOOL
  1566. CWebServiceInstallComponent::InitialMetabaseBackUp( BOOL bAdd )
  1567. {
  1568. TSTR strBackupName;
  1569. if ( !strBackupName.LoadString( IDS_INITIAL_METABASE_BK_NAME ) )
  1570. {
  1571. // Failed to get metabase name
  1572. return FALSE;
  1573. }
  1574. if ( bAdd )
  1575. {
  1576. return CMDKey::Backup( strBackupName.QueryStr(), // Backup Name
  1577. 1, // Version #
  1578. MD_BACKUP_OVERWRITE |
  1579. MD_BACKUP_SAVE_FIRST |
  1580. MD_BACKUP_FORCE_BACKUP ); // Overwrite if one already exists
  1581. }
  1582. return CMDKey::DeleteBackup( strBackupName.QueryStr(),
  1583. 1 );
  1584. }
  1585. // CWebServiceInstallComponent::
  1586. //
  1587. // If during upgrade, this metabase setting is set, add the inherit flag to it
  1588. // The reason for this was because it was not set in Win2k days, and now
  1589. // we need it set
  1590. //
  1591. BOOL
  1592. CWebServiceInstallComponent::AddInheritFlagToSSLUseDSMap()
  1593. {
  1594. CMDKey cmdKey;
  1595. CMDValue cmdValue;
  1596. if ( FAILED( cmdKey.OpenNode( METABASEPATH_WWW_ROOT ) ) )
  1597. {
  1598. // Failed to open metabase
  1599. return FALSE;
  1600. }
  1601. if ( cmdKey.GetData( cmdValue, MD_SSL_USE_DS_MAPPER ) &&
  1602. ( cmdValue.GetDataType() == DWORD_METADATA ) )
  1603. {
  1604. // If this value is present, then set with inheritance
  1605. cmdValue.SetAttributes( METADATA_INHERIT );
  1606. if ( !cmdKey.SetData( cmdValue, MD_SSL_USE_DS_MAPPER ) )
  1607. {
  1608. return FALSE;
  1609. }
  1610. }
  1611. return TRUE;
  1612. }
  1613. // SetRegEntries
  1614. //
  1615. // Set the appropriate registry entries
  1616. //
  1617. // Parameters:
  1618. // bAdd - [in] TRUE == Add; FALSE == Remove
  1619. //
  1620. BOOL
  1621. CWebServiceInstallComponent::SetRegEntries( BOOL bAdd )
  1622. {
  1623. CRegistry Registry;
  1624. if ( !Registry.OpenRegistry( HKEY_LOCAL_MACHINE,
  1625. REG_HTTPSYS_PARAM,
  1626. KEY_WRITE ) )
  1627. {
  1628. // Failed to open registry Key
  1629. return FALSE;
  1630. }
  1631. if ( bAdd )
  1632. {
  1633. CRegValue Value;
  1634. if ( !Value.SetDword( 1 ) ||
  1635. !Registry.SetValue( REG_HTTPSYS_DISABLESERVERHEADER, Value ) )
  1636. {
  1637. // Failed to set
  1638. return FALSE;
  1639. }
  1640. }
  1641. else
  1642. {
  1643. Registry.DeleteValue( REG_HTTPSYS_DISABLESERVERHEADER );
  1644. }
  1645. return TRUE;
  1646. }
  1647. // function: UpdateSiteFiltersAcl
  1648. //
  1649. // Update all the SiteFilter's Acl's with the new ACL
  1650. //
  1651. // Return Value:
  1652. // TRUE - Success change
  1653. // FALSE - Failure changing
  1654. BOOL
  1655. CWebServiceInstallComponent::UpdateSiteFiltersAcl()
  1656. {
  1657. CMDKey cmdKey;
  1658. CMDValue cmdValue;
  1659. CMDValue cmdIISFiltersValue;
  1660. WCHAR szSubNode[METADATA_MAX_NAME_LEN];
  1661. TSTR strFilterKey;
  1662. DWORD i = 0;
  1663. iisDebugOut((LOG_TYPE_PROGRAM_FLOW, _T("Calling UpdateSiteFiltersAcl\n")));
  1664. if ( !RetrieveFiltersAcl( &cmdValue ) )
  1665. {
  1666. // There is no acl to set, so lets exit
  1667. return TRUE;
  1668. }
  1669. if ( FAILED( cmdKey.OpenNode( METABASEPATH_WWW_ROOT ) ) ||
  1670. !cmdIISFiltersValue.SetValue( MD_KEY_TYPE, // ID
  1671. 0, // Attributes
  1672. IIS_MD_UT_SERVER, // UserType
  1673. STRING_METADATA, // DataType
  1674. ( _tcslen( KEYTYPE_FILTERS ) + 1 ) * sizeof(TCHAR),
  1675. KEYTYPE_FILTERS ) ) // Value
  1676. {
  1677. // Failed to open filters node
  1678. return FALSE;
  1679. }
  1680. while ( cmdKey.EnumKeys( szSubNode, i++ ) )
  1681. {
  1682. if ( !IsNumber( szSubNode ) )
  1683. {
  1684. // Since it is not a number, it is not a website, so lets skip
  1685. continue;
  1686. }
  1687. if ( !strFilterKey.Copy( szSubNode ) ||
  1688. !strFilterKey.Append( METABASEPATH_FILTER_PATH ) )
  1689. {
  1690. return FALSE;
  1691. }
  1692. // Add the filters node if not already there
  1693. cmdKey.AddNode( strFilterKey.QueryStr() );
  1694. if ( !cmdKey.SetData( cmdIISFiltersValue, MD_KEY_TYPE, strFilterKey.QueryStr() ) ||
  1695. !cmdKey.SetData( cmdValue, MD_ADMIN_ACL, strFilterKey.QueryStr() ) )
  1696. {
  1697. // Failed to set ACL
  1698. return FALSE;
  1699. }
  1700. }
  1701. return TRUE;
  1702. }
  1703. // function: RetrieveFiltersAcl
  1704. //
  1705. // Retrieve the Filters ACL to use
  1706. //
  1707. BOOL
  1708. CWebServiceInstallComponent::RetrieveFiltersAcl(CMDValue *pcmdValue)
  1709. {
  1710. CMDKey cmdKey;
  1711. if ( FAILED( cmdKey.OpenNode( METABASEPATH_FILTER_GLOBAL_ROOT ) ) )
  1712. {
  1713. // Failed to open filters node
  1714. return FALSE;
  1715. }
  1716. // Don't inherit acl, but do retrieve if it should be inheritted
  1717. pcmdValue->SetAttributes( METADATA_ISINHERITED );
  1718. if ( !cmdKey.GetData( *pcmdValue, MD_ADMIN_ACL ) )
  1719. {
  1720. // Failed to retrieve value
  1721. return FALSE;
  1722. }
  1723. return TRUE;
  1724. }
  1725. // function: IsNumber
  1726. //
  1727. // Determine if the string is a number
  1728. //
  1729. BOOL
  1730. CWebServiceInstallComponent::IsNumber( LPWSTR szString )
  1731. {
  1732. while ( *szString )
  1733. {
  1734. if ( ( *szString < '0' ) ||
  1735. ( *szString > '9' ) )
  1736. {
  1737. return FALSE;
  1738. }
  1739. szString++;
  1740. }
  1741. return TRUE;
  1742. }