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.

3212 lines
67 KiB

  1. /*++
  2. Copyright (c) 1994-2000 Microsoft Corporation
  3. Module Name :
  4. inetprop.cpp
  5. Abstract:
  6. Internet Properties base classes
  7. Author:
  8. Ronald Meijer (ronaldm)
  9. Sergei Antonov (sergeia)
  10. Project:
  11. Internet Services Manager
  12. Revision History:
  13. --*/
  14. #include "stdafx.h"
  15. #include "common.h"
  16. #include "InetMgrApp.h"
  17. #include "inetprop.h"
  18. #include "mmc.h"
  19. extern "C"
  20. {
  21. #include <lm.h>
  22. }
  23. #ifdef _DEBUG
  24. #undef THIS_FILE
  25. static char BASED_CODE THIS_FILE[] = __FILE__;
  26. #endif
  27. #define new DEBUG_NEW
  28. //
  29. // Period to sleep while waiting for service to attain desired state
  30. //
  31. #define SLEEP_INTERVAL (500L)
  32. //
  33. // Maximum time to wait for service to attain desired state
  34. //
  35. #define MAX_SLEEP (180000) // For a service
  36. #define MAX_SLEEP_INST ( 30000) // For an instance
  37. //
  38. // Instance numbers
  39. //
  40. #define FIRST_INSTANCE (1)
  41. #define LAST_INSTANCE (0xffffffff)
  42. #define MAX_INSTANCE_LEN (32)
  43. //
  44. // Calling instance
  45. //
  46. //HINSTANCE hDLLInstance;
  47. //
  48. // Utility Functions
  49. //
  50. // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  51. const LPCTSTR g_cszTemplates = SZ_MBN_INFO SZ_MBN_SEP_STR SZ_MBN_TEMPLATES;
  52. const LPCTSTR g_cszCompression = SZ_MBN_FILTERS SZ_MBN_SEP_STR SZ_MBN_COMPRESSION SZ_MBN_SEP_STR SZ_MBN_PARAMETERS;
  53. const LPCTSTR g_cszMachine = SZ_MBN_MACHINE;
  54. const LPCTSTR g_cszMimeMap = SZ_MBN_MIMEMAP;
  55. const LPCTSTR g_cszRoot = SZ_MBN_ROOT;
  56. const LPCTSTR g_cszSep = SZ_MBN_SEP_STR;
  57. const LPCTSTR g_cszInfo = SZ_MBN_INFO;
  58. const TCHAR g_chSep = SZ_MBN_SEP_CHAR;
  59. /*
  60. NET_API_STATUS
  61. ChangeInetServiceState(
  62. IN LPCTSTR lpszServer,
  63. IN LPCTSTR lpszService,
  64. IN int nNewState,
  65. OUT int * pnCurrentState
  66. )
  67. /*++
  68. Routine Description:
  69. Start/stop/pause or continue a _service_
  70. Arguments:
  71. LPCTSTR lpszServer : Server name
  72. LPCTSTR lpszService : Service name
  73. int nNewState : INetService* definition.
  74. int * pnCurrentState : Ptr to current state (will be changed)
  75. Return Value:
  76. Error return code
  77. --/
  78. {
  79. #ifdef NO_SERVICE_CONTROLLER
  80. *pnCurrentState = INetServiceUnknown;
  81. return ERROR_SERVICE_REQUEST_TIMEOUT;
  82. #else
  83. SC_HANDLE hService = NULL;
  84. SC_HANDLE hScManager = NULL;
  85. NET_API_STATUS err = ERROR_SUCCESS;
  86. do
  87. {
  88. hScManager = ::OpenSCManager(lpszServer, NULL, SC_MANAGER_ALL_ACCESS);
  89. if (hScManager == NULL)
  90. {
  91. err = ::GetLastError();
  92. break;
  93. }
  94. hService = ::OpenService(hScManager, lpszService, SERVICE_ALL_ACCESS);
  95. if (hService == NULL)
  96. {
  97. err = ::GetLastError();
  98. break;
  99. }
  100. BOOL fSuccess = FALSE;
  101. DWORD dwTargetState;
  102. DWORD dwPendingState;
  103. SERVICE_STATUS ss;
  104. switch(nNewState)
  105. {
  106. case INetServiceStopped:
  107. dwTargetState = SERVICE_STOPPED;
  108. dwPendingState = SERVICE_STOP_PENDING;
  109. fSuccess = ::ControlService(hService, SERVICE_CONTROL_STOP, &ss);
  110. break;
  111. case INetServiceRunning:
  112. dwTargetState = SERVICE_RUNNING;
  113. if (*pnCurrentState == INetServicePaused)
  114. {
  115. dwPendingState = SERVICE_CONTINUE_PENDING;
  116. fSuccess = ::ControlService(hService,
  117. SERVICE_CONTROL_CONTINUE, &ss);
  118. }
  119. else
  120. {
  121. dwPendingState = SERVICE_START_PENDING;
  122. fSuccess = ::StartService(hService, 0, NULL);
  123. }
  124. break;
  125. case INetServicePaused:
  126. dwTargetState = SERVICE_PAUSED;
  127. dwPendingState = SERVICE_PAUSE_PENDING;
  128. fSuccess = ::ControlService(hService, SERVICE_CONTROL_PAUSE, &ss);
  129. break;
  130. default:
  131. ASSERT_MSG("Invalid service state requested");
  132. err = ERROR_INVALID_PARAMETER;
  133. }
  134. if (!fSuccess && err == ERROR_SUCCESS)
  135. {
  136. err = ::GetLastError();
  137. }
  138. //
  139. // Wait for the service to attain desired state, timeout
  140. // after 3 minutes.
  141. //
  142. DWORD dwSleepTotal = 0L;
  143. while (dwSleepTotal < MAX_SLEEP)
  144. {
  145. if (!::QueryServiceStatus(hService, &ss))
  146. {
  147. err = ::GetLastError();
  148. break;
  149. }
  150. if (ss.dwCurrentState != dwPendingState)
  151. {
  152. //
  153. // Done one way or another
  154. //
  155. if (ss.dwCurrentState != dwTargetState)
  156. {
  157. //
  158. // Did not achieve desired result. Something went
  159. // wrong.
  160. //
  161. if (ss.dwWin32ExitCode)
  162. {
  163. err = ss.dwWin32ExitCode;
  164. }
  165. }
  166. break;
  167. }
  168. //
  169. // Still pending...
  170. //
  171. ::Sleep(SLEEP_INTERVAL);
  172. dwSleepTotal += SLEEP_INTERVAL;
  173. }
  174. if (dwSleepTotal >= MAX_SLEEP)
  175. {
  176. err = ERROR_SERVICE_REQUEST_TIMEOUT;
  177. }
  178. //
  179. // Update state information
  180. //
  181. switch(ss.dwCurrentState)
  182. {
  183. case SERVICE_STOPPED:
  184. case SERVICE_STOP_PENDING:
  185. *pnCurrentState = INetServiceStopped;
  186. break;
  187. case SERVICE_RUNNING:
  188. case SERVICE_START_PENDING:
  189. case SERVICE_CONTINUE_PENDING:
  190. *pnCurrentState = INetServiceRunning;
  191. break;
  192. case SERVICE_PAUSE_PENDING:
  193. case SERVICE_PAUSED:
  194. *pnCurrentState = INetServicePaused;
  195. break;
  196. default:
  197. *pnCurrentState = INetServiceUnknown;
  198. }
  199. }
  200. while(FALSE);
  201. if (hService)
  202. {
  203. ::CloseServiceHandle(hService);
  204. }
  205. if (hScManager)
  206. {
  207. ::CloseServiceHandle(hScManager);
  208. }
  209. return err;
  210. #endif // NO_SERVICE_CONTROLLER
  211. }
  212. */
  213. BOOL
  214. DoesServerExist(
  215. IN LPCTSTR lpszServer
  216. )
  217. /*++
  218. Routine Description:
  219. Check to make sure the machine exists
  220. Arguments:
  221. LPCTSTR lpszServer : machine name
  222. Return Value:
  223. TRUE if the server exists, FALSE otherwise.
  224. --*/
  225. {
  226. #ifdef NO_SERVICE_CONTROLLER
  227. //
  228. // Assume it exists
  229. //
  230. return TRUE;
  231. #else
  232. //
  233. // CODEWORK: This is not the best way to do this, especially
  234. // not across proxies and what not.
  235. //
  236. SC_HANDLE hScManager;
  237. NET_API_STATUS err = ERROR_SUCCESS;
  238. hScManager = ::OpenSCManager(lpszServer, NULL, SC_MANAGER_CONNECT);
  239. if (hScManager == NULL)
  240. {
  241. err = ::GetLastError();
  242. }
  243. ::CloseServiceHandle(hScManager);
  244. return err != RPC_S_SERVER_UNAVAILABLE;
  245. #endif // NO_SERVICE_CONTROLLER
  246. }
  247. //
  248. // CMetaProperties implementation
  249. //
  250. // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  251. CMetaProperties::CMetaProperties(
  252. IN CComAuthInfo * pAuthInfo OPTIONAL,
  253. IN LPCTSTR lpszMDPath
  254. )
  255. /*++
  256. Routine Description:
  257. Constructor -- creates the interface
  258. Arguments:
  259. CIISServer * pAuthInfo : Auth info. NULL indicates the local computer
  260. LPCTSTR lpszMDPath : Metabase path
  261. Return Value:
  262. N/A
  263. --*/
  264. : m_hResult(S_OK),
  265. m_dwNumEntries(0),
  266. m_dwMDUserType(ALL_METADATA),
  267. m_dwMDDataType(ALL_METADATA),
  268. m_dwMDDataLen(0),
  269. m_pbMDData(NULL),
  270. m_fInherit(TRUE),
  271. m_strMetaRoot(lpszMDPath),
  272. CMetaKey(pAuthInfo)
  273. {
  274. CMetabasePath::CleanMetaPath(m_strMetaRoot);
  275. }
  276. CMetaProperties::CMetaProperties(
  277. IN CMetaInterface * pInterface,
  278. IN LPCTSTR lpszMDPath
  279. )
  280. /*++
  281. Routine Description:
  282. Constructor -- attach to an existing interface.
  283. Arguments:
  284. CMetaInterface * pInterface : Existing interface
  285. LPCTSTR lpszMDPath : Metabase path
  286. Return Value:
  287. N/A
  288. --*/
  289. : m_hResult(S_OK),
  290. m_dwNumEntries(0),
  291. m_dwMDUserType(ALL_METADATA),
  292. m_dwMDDataType(ALL_METADATA),
  293. m_dwMDDataLen(0),
  294. m_pbMDData(NULL),
  295. m_fInherit(TRUE),
  296. m_strMetaRoot(lpszMDPath),
  297. CMetaKey(pInterface)
  298. {
  299. CMetabasePath::CleanMetaPath(m_strMetaRoot);
  300. }
  301. CMetaProperties::CMetaProperties(
  302. IN CMetaKey * pKey,
  303. IN LPCTSTR lpszMDPath
  304. )
  305. /*++
  306. Routine Description:
  307. Construct from open key
  308. Arguments:
  309. CMetaKey * pKey : Open key
  310. LPCTSTR lpszMDPath : Path
  311. Return Value:
  312. N/A
  313. --*/
  314. : m_hResult(S_OK),
  315. m_dwNumEntries(0),
  316. m_dwMDUserType(ALL_METADATA),
  317. m_dwMDDataType(ALL_METADATA),
  318. m_dwMDDataLen(0),
  319. m_pbMDData(NULL),
  320. m_strMetaRoot(lpszMDPath),
  321. m_fInherit(TRUE),
  322. CMetaKey(FALSE, pKey)
  323. {
  324. CMetabasePath::CleanMetaPath(m_strMetaRoot);
  325. }
  326. CMetaProperties::~CMetaProperties()
  327. /*++
  328. Routine Description:
  329. Destructor -- clean up
  330. Arguments:
  331. N/A
  332. Return Value:
  333. N/A
  334. --*/
  335. {
  336. Cleanup();
  337. }
  338. /* virtual */
  339. HRESULT
  340. CMetaProperties::LoadData()
  341. /*++
  342. Routine Description:
  343. Fetch all data with or without inheritance, and call the derived
  344. class to parse the data into fields.
  345. Arguments:
  346. None
  347. Return Value:
  348. HRESULT
  349. --*/
  350. {
  351. //
  352. // Get all data off the master root
  353. //
  354. DWORD dwMDAttributes = METADATA_NO_ATTRIBUTES;
  355. if (m_fInherit)
  356. {
  357. dwMDAttributes = METADATA_INHERIT
  358. | METADATA_PARTIAL_PATH
  359. | METADATA_ISINHERITED;
  360. }
  361. m_hResult = GetAllData(
  362. dwMDAttributes,
  363. m_dwMDUserType,
  364. m_dwMDDataType,
  365. &m_dwNumEntries,
  366. &m_dwMDDataLen,
  367. &m_pbMDData,
  368. m_strMetaRoot
  369. );
  370. if (SUCCEEDED(m_hResult))
  371. {
  372. //
  373. // Call the derived class to break up data into fields
  374. //
  375. ParseFields();
  376. }
  377. Cleanup();
  378. return m_hResult;
  379. }
  380. void
  381. CMetaProperties::Cleanup()
  382. /*++
  383. Routine Description:
  384. Free data
  385. Arguments:
  386. None
  387. Return Value:
  388. None
  389. --*/
  390. {
  391. SAFE_FREEMEM(m_pbMDData);
  392. m_dwNumEntries = 0;
  393. m_dwMDDataLen = 0;
  394. }
  395. /* virtual */
  396. HRESULT
  397. CMetaProperties::QueryResult() const
  398. /*++
  399. Routine Description:
  400. Determine the construction return code
  401. Arguments:
  402. None
  403. Return Value:
  404. HRESULT
  405. --*/
  406. {
  407. HRESULT hr = CMetaKey::QueryResult();
  408. return SUCCEEDED(hr) ? m_hResult : hr;
  409. }
  410. HRESULT
  411. RebindInterface(CMetaInterface * pInterface,
  412. BOOL * pfContinue, IN DWORD dwCancelError);
  413. HRESULT
  414. CMetaProperties::OpenForWriting(
  415. IN BOOL fCreate OPTIONAL
  416. )
  417. /*++
  418. Routine Description:
  419. Attempt to open the path for writing. If fCreate is TRUE
  420. (default), then create the path if it doesn't yet exist
  421. Arguments:
  422. BOOL fCreate : If TRUE, create the path if it doesn't exist.
  423. Return Value:
  424. HRESULT
  425. Notes:
  426. If the key is already open, this will fire an ASSERT and close
  427. it.
  428. --*/
  429. {
  430. CError err;
  431. if (IsOpen())
  432. {
  433. ASSERT_MSG("Key already open -- closing");
  434. Close();
  435. }
  436. BOOL fNewPath, fRepeat;
  437. do
  438. {
  439. fNewPath = FALSE;
  440. fRepeat = FALSE;
  441. err = Open(METADATA_PERMISSION_WRITE, m_strMetaRoot);
  442. if (err.Win32Error() == ERROR_PATH_NOT_FOUND && fCreate)
  443. {
  444. err = CreatePathFromFailedOpen();
  445. fNewPath = err.Succeeded();
  446. }
  447. else if (err.Win32Error() == RPC_S_SERVER_UNAVAILABLE)
  448. {
  449. err = RebindInterface(this, &fRepeat, ERROR_CANCELLED);
  450. }
  451. } while(fNewPath || fRepeat);
  452. return err;
  453. }
  454. //
  455. // Machine properties
  456. //
  457. // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  458. CMachineProps::CMachineProps(
  459. IN CComAuthInfo * pAuthInfo OPTIONAL
  460. )
  461. : CMetaProperties(pAuthInfo, CMetabasePath()),
  462. m_fEnableMetabaseEdit(TRUE),
  463. m_fUTF8Web(FALSE)
  464. {
  465. // The only property we have here should actually be on metabase root
  466. m_strMetaRoot = SZ_MBN_SEP_CHAR;
  467. m_strMetaRoot += SZ_MBN_MACHINE;
  468. }
  469. CMachineProps::CMachineProps(
  470. IN CMetaInterface * pInterface
  471. )
  472. : CMetaProperties(pInterface, CMetabasePath()),
  473. m_fEnableMetabaseEdit(TRUE),
  474. m_fUTF8Web(FALSE)
  475. {
  476. // The only property we have here should actually be on metabase root
  477. m_strMetaRoot = SZ_MBN_SEP_CHAR;
  478. m_strMetaRoot += SZ_MBN_MACHINE;
  479. }
  480. /* virtual */
  481. void
  482. CMachineProps::ParseFields()
  483. /*++
  484. Routine Description:
  485. Parse the fetched data into fields
  486. --*/
  487. {
  488. BEGIN_PARSE_META_RECORDS(m_dwNumEntries, m_pbMDData)
  489. HANDLE_META_RECORD(MD_ROOT_ENABLE_EDIT_WHILE_RUNNING, m_fEnableMetabaseEdit)
  490. END_PARSE_META_RECORDS
  491. CError err;
  492. BOOL fClose = FALSE;
  493. do
  494. {
  495. if (!IsOpen())
  496. {
  497. err = Open(METADATA_PERMISSION_READ, m_strMetaRoot);
  498. BREAK_ON_ERR_FAILURE(err);
  499. fClose = TRUE;
  500. }
  501. DWORD val = 0;
  502. err = QueryValue(MD_GLOBAL_LOG_IN_UTF_8, val, NULL, SZ_MBN_WEB);
  503. BREAK_ON_ERR_FAILURE(err);
  504. MP_V(m_fUTF8Web) = val;
  505. } while (FALSE);
  506. if (fClose)
  507. {
  508. Close();
  509. }
  510. }
  511. HRESULT
  512. CMachineProps::WriteDirtyProps()
  513. {
  514. CError err;
  515. BOOL fFlush = MP_D(m_fEnableMetabaseEdit);
  516. BEGIN_META_WRITE()
  517. META_WRITE(MD_ROOT_ENABLE_EDIT_WHILE_RUNNING, m_fEnableMetabaseEdit)
  518. END_META_WRITE(err);
  519. if (fFlush)
  520. {
  521. err = SaveData();
  522. //RefreshMetabaseSystemChangeNumber();
  523. }
  524. do // manually because it is going to services paths
  525. {
  526. BOOL fClose = FALSE;
  527. if (MP_D(m_fUTF8Web))
  528. {
  529. if (!IsOpen())
  530. {
  531. err = OpenForWriting();
  532. BREAK_ON_ERR_FAILURE(err);
  533. fClose = TRUE;
  534. }
  535. err = SetValue(MD_GLOBAL_LOG_IN_UTF_8, MP_V(m_fUTF8Web), NULL, SZ_MBN_WEB);
  536. BREAK_ON_ERR_FAILURE(err);
  537. MP_D(m_fUTF8Web) = FALSE;
  538. CMetabasePath path(FALSE, m_strMetaRoot, SZ_MBN_WEB);
  539. err = CheckDescendants(MD_GLOBAL_LOG_IN_UTF_8, &m_auth, path);
  540. BREAK_ON_ERR_FAILURE(err);
  541. }
  542. if (fClose)
  543. {
  544. Close();
  545. }
  546. } while (FALSE);
  547. return err;
  548. }
  549. //
  550. // Compression Properties
  551. //
  552. // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  553. CIISCompressionProps::CIISCompressionProps(
  554. IN CComAuthInfo * pAuthInfo OPTIONAL
  555. )
  556. /*++
  557. Routine Description:
  558. Constructor for compression properties object
  559. Arguments:
  560. CComAuthInfo * pAuthInfo : Auth info. NULL indicates the local computer
  561. Return Value:
  562. N/A
  563. --*/
  564. : CMetaProperties(
  565. pAuthInfo,
  566. CMetabasePath(SZ_MBN_WEB, MASTER_INSTANCE, g_cszCompression)
  567. ),
  568. //
  569. // Default properties
  570. //
  571. m_fEnableStaticCompression(FALSE),
  572. m_fEnableDynamicCompression(FALSE),
  573. m_fLimitDirectorySize(FALSE),
  574. m_fPathDoesNotExist(FALSE),
  575. m_dwDirectorySize(0xffffffff),
  576. m_strDirectory()
  577. {
  578. //
  579. // Override base parameters
  580. //
  581. m_fInherit = FALSE;
  582. }
  583. /* virtual */
  584. HRESULT
  585. CIISCompressionProps::LoadData()
  586. /*++
  587. Routine Description:
  588. Fetch all data with or without inheritance, and call the derived
  589. class to parse the data into fields.
  590. Arguments:
  591. None
  592. Return Value:
  593. HRESULT
  594. --*/
  595. {
  596. CError err(CMetaProperties::LoadData());
  597. m_fPathDoesNotExist = (err.Win32Error() == ERROR_PATH_NOT_FOUND);
  598. return err;
  599. }
  600. /* virtual */
  601. void
  602. CIISCompressionProps::ParseFields()
  603. /*++
  604. Routine Description:
  605. Parse the fetched data into fields
  606. Arguments:
  607. None
  608. Return Value:
  609. None
  610. --*/
  611. {
  612. BEGIN_PARSE_META_RECORDS(m_dwNumEntries, m_pbMDData)
  613. HANDLE_META_RECORD(MD_HC_DO_STATIC_COMPRESSION, m_fEnableStaticCompression)
  614. HANDLE_META_RECORD(MD_HC_DO_DYNAMIC_COMPRESSION, m_fEnableDynamicCompression)
  615. HANDLE_META_RECORD(MD_HC_DO_DISK_SPACE_LIMITING, m_fLimitDirectorySize)
  616. HANDLE_META_RECORD(MD_HC_MAX_DISK_SPACE_USAGE, m_dwDirectorySize)
  617. HANDLE_META_RECORD(MD_HC_COMPRESSION_DIRECTORY, m_strDirectory)
  618. END_PARSE_META_RECORDS
  619. }
  620. /* virtual */
  621. HRESULT
  622. CIISCompressionProps::WriteDirtyProps()
  623. /*++
  624. Routine Description:
  625. Write dirty properties
  626. Arguments:
  627. None
  628. Return Value:
  629. HRESULT
  630. --*/
  631. {
  632. CError err;
  633. BEGIN_META_WRITE()
  634. META_WRITE(MD_HC_DO_STATIC_COMPRESSION, m_fEnableStaticCompression)
  635. META_WRITE(MD_HC_DO_DYNAMIC_COMPRESSION, m_fEnableDynamicCompression)
  636. META_WRITE(MD_HC_DO_DISK_SPACE_LIMITING, m_fLimitDirectorySize)
  637. META_WRITE(MD_HC_MAX_DISK_SPACE_USAGE, m_dwDirectorySize)
  638. META_WRITE(MD_HC_COMPRESSION_DIRECTORY, m_strDirectory)
  639. END_META_WRITE(err);
  640. return err;
  641. }
  642. //
  643. // Mime Types Properties
  644. //
  645. // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  646. CMimeTypes::CMimeTypes(
  647. IN CComAuthInfo * pAuthInfo OPTIONAL,
  648. IN LPCTSTR lpszMDPath
  649. )
  650. /*++
  651. Routine Description:
  652. Mime types list constructor
  653. Arguments:
  654. CComAuthInfo * pAuthInfo : Auth info. NULL indicates the local computer
  655. LPCTSTR lpszMDPath : Metabase path
  656. Return Value:
  657. N/A
  658. --*/
  659. : CMetaProperties(
  660. pAuthInfo,
  661. lpszMDPath
  662. /*
  663. lpszService,
  664. dwInstance,
  665. lpszParent,
  666. dwInstance == MASTER_INSTANCE && lpszService == NULL
  667. ? g_cszMimeMap
  668. : lpszAlias
  669. */
  670. //
  671. // BUGBUG: dwInstance == MASTER_INSTANCE and g_cszMimeMap not used
  672. ),
  673. //
  674. // Default properties
  675. //
  676. m_strlMimeTypes()
  677. {
  678. }
  679. CMimeTypes::CMimeTypes(
  680. IN CMetaInterface * pInterface,
  681. IN LPCTSTR lpszMDPath
  682. )
  683. /*++
  684. Routine Description:
  685. Mime types list constructor
  686. Arguments:
  687. CMetaInterface * pInterface : Existing interface
  688. LPCTSTR lpszMDPath : Metabase path
  689. Return Value:
  690. N/A
  691. --*/
  692. : CMetaProperties(
  693. pInterface,
  694. lpszMDPath
  695. /*
  696. lpszService,
  697. dwInstance,
  698. lpszParent,
  699. dwInstance == MASTER_INSTANCE && lpszService == NULL
  700. ? g_cszMimeMap
  701. : lpszAlias
  702. */
  703. //
  704. // BUGBUG: MASTER_INSTANCE, g_cszMimeMap not used
  705. //
  706. ),
  707. //
  708. // Default properties
  709. //
  710. m_strlMimeTypes()
  711. {
  712. }
  713. void
  714. CMimeTypes::ParseFields()
  715. /*++
  716. Routine Description:
  717. Parse the fetched data into fields
  718. Arguments:
  719. None
  720. Return Value:
  721. None
  722. --*/
  723. {
  724. BEGIN_PARSE_META_RECORDS(m_dwNumEntries, m_pbMDData)
  725. HANDLE_META_RECORD(MD_MIME_MAP, m_strlMimeTypes)
  726. END_PARSE_META_RECORDS
  727. }
  728. /* virtual */
  729. HRESULT
  730. CMimeTypes::WriteDirtyProps()
  731. /*++
  732. Routine Description:
  733. Write the dirty properties to the metabase
  734. Arguments:
  735. None
  736. Return Value:
  737. HRESULT
  738. --*/
  739. {
  740. CError err;
  741. BEGIN_META_WRITE()
  742. META_WRITE(MD_MIME_MAP, m_strlMimeTypes);
  743. END_META_WRITE(err);
  744. return err;
  745. }
  746. //
  747. // Server Capabilities
  748. //
  749. // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  750. CServerCapabilities::CServerCapabilities(
  751. IN CComAuthInfo * pAuthInfo OPTIONAL,
  752. IN LPCTSTR lpszMDPath
  753. )
  754. /*++
  755. Routine Description:
  756. Constructor for server capabilities object
  757. Arguments:
  758. CComAuthInfo * pAuthInfo : Server name. NULL indicates the local computer
  759. LPCTSTR lpszMDPath : e.g. "lm/w3svc/info"
  760. Return Value:
  761. N/A
  762. --*/
  763. : CMetaProperties(pAuthInfo, lpszMDPath),
  764. //
  765. // Default properties
  766. //
  767. m_dwPlatform(),
  768. m_dwVersionMajor(),
  769. m_dwVersionMinor(),
  770. m_dwCapabilities((DWORD)~IIS_CAP1_10_CONNECTION_LIMIT),
  771. m_dwConfiguration(0L)
  772. {
  773. m_dwMDUserType = IIS_MD_UT_SERVER;
  774. m_dwMDDataType = DWORD_METADATA;
  775. }
  776. CServerCapabilities::CServerCapabilities(
  777. IN CMetaInterface * pInterface,
  778. IN LPCTSTR lpszMDPath
  779. )
  780. /*++
  781. Routine Description:
  782. Constructor for server capabilities object that uses an existing interface.
  783. Arguments:
  784. CMetaInterface * pInterface : Existing interface
  785. LPCTSTR lpszMDPath : e.g. "lm/w3svc/info"
  786. Return Value:
  787. N/A
  788. --*/
  789. : CMetaProperties(pInterface, lpszMDPath),
  790. //
  791. // Default properties
  792. //
  793. m_dwPlatform(),
  794. m_dwVersionMajor(),
  795. m_dwVersionMinor(),
  796. m_dwCapabilities((DWORD)~IIS_CAP1_10_CONNECTION_LIMIT),
  797. m_dwConfiguration(0L)
  798. {
  799. m_dwMDUserType = IIS_MD_UT_SERVER;
  800. m_dwMDDataType = DWORD_METADATA;
  801. }
  802. /* virtual */
  803. void
  804. CServerCapabilities::ParseFields()
  805. /*++
  806. Routine Description:
  807. Parse the fetched data into fields
  808. Arguments:
  809. None
  810. Return Value:
  811. None
  812. --*/
  813. {
  814. //
  815. // Only reading UT_SERVER, DWORD_METADATA.
  816. //
  817. BEGIN_PARSE_META_RECORDS(m_dwNumEntries, m_pbMDData)
  818. HANDLE_META_RECORD(MD_SERVER_PLATFORM, m_dwPlatform)
  819. HANDLE_META_RECORD(MD_SERVER_VERSION_MAJOR, m_dwVersionMajor)
  820. HANDLE_META_RECORD(MD_SERVER_VERSION_MINOR, m_dwVersionMinor)
  821. HANDLE_META_RECORD(MD_SERVER_CAPABILITIES, m_dwCapabilities)
  822. HANDLE_META_RECORD(MD_SERVER_CONFIGURATION_INFO, m_dwConfiguration)
  823. END_PARSE_META_RECORDS
  824. }
  825. //
  826. // Instance Properties
  827. //
  828. // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  829. /* static */
  830. LPCTSTR
  831. CInstanceProps::GetDisplayText(
  832. OUT CString & strName,
  833. IN LPCTSTR szComment,
  834. IN LPCTSTR szHostHeaderName,
  835. IN CIPAddress & ia,
  836. IN UINT uPort,
  837. IN DWORD dwID
  838. )
  839. /*++
  840. Routine Description:
  841. Build display text from instance information
  842. Arguments:
  843. CString & strName
  844. LPCTSTR szComment
  845. LPCTSTR szHostHeaderName
  846. LPCTSTR szServiceName
  847. CIPAddress & ia
  848. UINT uPort
  849. DWORD dwID
  850. Return Value:
  851. Pointer to the name buffer.
  852. --*/
  853. {
  854. //
  855. // Generate display name
  856. //
  857. // First use the comment,
  858. // if that's not available, use the host header name,
  859. // if that's not available, use the IP address:port.
  860. // If that's not available, use the instance number.
  861. //
  862. //
  863. CComBSTR bstrFmt;
  864. if (szComment && *szComment)
  865. {
  866. strName = szComment;
  867. }
  868. else if (szHostHeaderName && *szHostHeaderName)
  869. {
  870. strName = szHostHeaderName;
  871. }
  872. else
  873. {
  874. if(!ia.IsZeroValue() && uPort != 0)
  875. {
  876. VERIFY(bstrFmt.LoadString(IDS_INSTANCE_PORT_FMT));
  877. strName.Format(bstrFmt,(LPCTSTR)ia, uPort);
  878. }
  879. else
  880. {
  881. VERIFY(bstrFmt.LoadString(IDS_INSTANCE_DEF_FMT));
  882. strName.Format(bstrFmt, dwID);
  883. }
  884. }
  885. return strName;
  886. }
  887. /* static */
  888. void
  889. CInstanceProps::CrackBinding(
  890. IN CString strBinding,
  891. OUT CIPAddress & iaIpAddress,
  892. OUT UINT & nTCPPort,
  893. OUT CString & strDomainName
  894. )
  895. /*++
  896. Routine Description:
  897. Helper function to crack a binding string
  898. Arguments:
  899. CString strBinding : Binding string to be parsed
  900. CIPAddress & iaIpAddress : IP Address output
  901. UINT & nTCPPort : TCP Port
  902. CString & strDomainName : Domain (host) header name
  903. Return Value:
  904. None
  905. --*/
  906. {
  907. //
  908. // Zero initialize
  909. //
  910. iaIpAddress.SetZeroValue();
  911. nTCPPort = 0;
  912. strDomainName.Empty();
  913. int iColonPos = strBinding.Find(_TCHAR(':'));
  914. if(iColonPos != -1)
  915. {
  916. //
  917. // Get the IP address
  918. //
  919. iaIpAddress = strBinding.Left(iColonPos);
  920. //
  921. // Look for the second colon
  922. //
  923. strBinding = strBinding.Mid(iColonPos + 1);
  924. iColonPos = strBinding.Find(_TCHAR(':'));
  925. }
  926. if(iColonPos != -1)
  927. {
  928. //
  929. // Get the port number
  930. //
  931. nTCPPort = ::_ttol(strBinding.Left(iColonPos));
  932. //
  933. // Look for the NULL termination
  934. //
  935. strBinding = strBinding.Mid(iColonPos + 1);
  936. iColonPos = strBinding.Find(_TCHAR('\0'));
  937. }
  938. if(iColonPos != -1)
  939. {
  940. strDomainName = strBinding.Left(iColonPos);
  941. }
  942. }
  943. /* static */
  944. void
  945. CInstanceProps::CrackSecureBinding(
  946. IN CString strBinding,
  947. OUT CIPAddress & iaIpAddress,
  948. OUT UINT & nSSLPort
  949. )
  950. /*++
  951. Routine Description:
  952. Helper function to crack a secure binding string
  953. Arguments:
  954. CString strBinding : Binding string to be parsed
  955. CIPAddress & iaIpAddress : IP Address output
  956. UINT & nSSLPort : SSL Port
  957. Return Value:
  958. None
  959. --*/
  960. {
  961. //
  962. // Same as regular binding without domain name
  963. //
  964. CString strDomainName;
  965. CrackBinding(strBinding, iaIpAddress, nSSLPort, strDomainName);
  966. ASSERT(strDomainName.IsEmpty());
  967. }
  968. /* static */
  969. int
  970. CInstanceProps::FindMatchingSecurePort(
  971. IN CStringList & strlSecureBindings,
  972. IN CIPAddress & iaIPAddress,
  973. OUT UINT & nSSLPort
  974. )
  975. /*++
  976. Routine Description:
  977. Find the SSL port applicable to the given IP Address.
  978. Arguments:
  979. CStringList & strlSecureBindings : Input stringlist of secure bindings
  980. CIPAddress & iaIPAddress : IP Address to target
  981. UINT & nSSLPort : Returns the SSL Port
  982. Return Value:
  983. The index of the binding string, or -1 if not found.
  984. Notes:
  985. The SSL port will be set to 0, if the IP address does not exist.
  986. A 0.0.0.0 ip address translates to "All Unassigned".
  987. --*/
  988. {
  989. nSSLPort = 0;
  990. CIPAddress iaEmpty;
  991. int cItems = 0;
  992. UINT nPort = 0;
  993. POSITION pos = strlSecureBindings.GetHeadPosition();
  994. while(pos)
  995. {
  996. CString & strBinding = strlSecureBindings.GetNext(pos);
  997. CIPAddress ia;
  998. nPort = 0;
  999. CrackSecureBinding(strBinding, ia, nPort);
  1000. if (ia == iaIPAddress)
  1001. {
  1002. //
  1003. // Found it!
  1004. //
  1005. nSSLPort = nPort;
  1006. return cItems;
  1007. }
  1008. ++cItems;
  1009. }
  1010. // we didn't find a match
  1011. // check if there is an allassigned one
  1012. cItems = 0;
  1013. pos = strlSecureBindings.GetHeadPosition();
  1014. while(pos)
  1015. {
  1016. CString & strBinding = strlSecureBindings.GetNext(pos);
  1017. CIPAddress ia;
  1018. nPort = 0;
  1019. CrackSecureBinding(strBinding, ia, nPort);
  1020. if (ia == iaEmpty)
  1021. {
  1022. //
  1023. // Found it!
  1024. //
  1025. nSSLPort = nPort;
  1026. return cItems;
  1027. }
  1028. ++cItems;
  1029. }
  1030. //
  1031. // Not found
  1032. //
  1033. return -1;
  1034. }
  1035. /* static */
  1036. BOOL
  1037. CInstanceProps::IsPortInUse(
  1038. IN CStringList & strlBindings,
  1039. IN CIPAddress & iaIPAddress,
  1040. IN UINT nPort
  1041. )
  1042. /*++
  1043. Routine Description:
  1044. Check to see if the give ip address/port combination is in use.
  1045. Arguments:
  1046. CStringList & strlBindings : Input stringlist of bindings
  1047. CIPAddress & iaIpAddress : IP Address target
  1048. UINT nPort : Port
  1049. Return Value:
  1050. TRUE if the given ip address/port combo is in use
  1051. Notes:
  1052. Host header name is ignored
  1053. --*/
  1054. {
  1055. POSITION pos = strlBindings.GetHeadPosition();
  1056. while(pos)
  1057. {
  1058. CString & strBinding = strlBindings.GetNext(pos);
  1059. CIPAddress ia;
  1060. UINT n;
  1061. CString str;
  1062. CrackBinding(strBinding, ia, n, str);
  1063. if (ia == iaIPAddress && n == nPort)
  1064. {
  1065. //
  1066. // Found it!
  1067. //
  1068. return TRUE;
  1069. }
  1070. }
  1071. //
  1072. // Not found
  1073. //
  1074. return FALSE;
  1075. }
  1076. /* static */
  1077. void
  1078. CInstanceProps::BuildBinding(
  1079. OUT CString & strBinding,
  1080. IN CIPAddress & iaIpAddress,
  1081. IN UINT & nTCPPort,
  1082. IN CString & strDomainName
  1083. )
  1084. /*++
  1085. Routine Description:
  1086. Build up a binding string from its component parts
  1087. Arguments:
  1088. CString & strBinding : Output binding string
  1089. CIPAddress & iaIpAddress : ip address (could be 0.0.0.0)
  1090. UINT & nTCPPort : TCP Port
  1091. CString & strDomainName : Domain name (host header)
  1092. Return Value:
  1093. None.
  1094. --*/
  1095. {
  1096. if (!iaIpAddress.IsZeroValue())
  1097. {
  1098. strBinding.Format(
  1099. _T("%s:%d:%s"),
  1100. (LPCTSTR)iaIpAddress,
  1101. nTCPPort,
  1102. (LPCTSTR)strDomainName
  1103. );
  1104. }
  1105. else
  1106. {
  1107. //
  1108. // Leave the ip address field blank
  1109. //
  1110. strBinding.Format(_T(":%d:%s"), nTCPPort, (LPCTSTR)strDomainName);
  1111. }
  1112. }
  1113. /* static */
  1114. void
  1115. CInstanceProps::BuildSecureBinding(
  1116. OUT CString & strBinding,
  1117. IN CIPAddress & iaIpAddress,
  1118. IN UINT & nSSLPort
  1119. )
  1120. /*++
  1121. Routine Description:
  1122. Build up a binding string from its component parts
  1123. Arguments:
  1124. CString & strBinding : Output binding string
  1125. CIPAddress & iaIpAddress : ip address (could be 0.0.0.0)
  1126. UINT & nSSLPort : SSL Port
  1127. Return Value:
  1128. None.
  1129. --*/
  1130. {
  1131. CString strDomainName;
  1132. BuildBinding(strBinding, iaIpAddress, nSSLPort, strDomainName);
  1133. }
  1134. CInstanceProps::CInstanceProps(
  1135. IN CComAuthInfo * pAuthInfo OPTIONAL,
  1136. IN LPCTSTR lpszMDPath,
  1137. IN UINT nDefPort OPTIONAL
  1138. )
  1139. /*++
  1140. Routine Description:
  1141. Constructor for instance properties
  1142. Arguments:
  1143. CComAuthInfo * pAuthInfo : Auth info. NULL indicates the local computer
  1144. LPCTSTR lpszMDPath : Metabase path
  1145. UINT nDefPort : Default port
  1146. Return Value:
  1147. N/A
  1148. --*/
  1149. : CMetaProperties(pAuthInfo, lpszMDPath),
  1150. m_dwWin32Error(ERROR_SUCCESS),
  1151. //
  1152. // Default Instance Values
  1153. //
  1154. m_strlBindings(),
  1155. m_strComment(),
  1156. m_fCluster(FALSE),
  1157. m_nTCPPort(nDefPort),
  1158. m_iaIpAddress(NULL_IP_ADDRESS),
  1159. m_strDomainName(),
  1160. m_dwState(MD_SERVER_STATE_STOPPED)
  1161. {
  1162. //
  1163. // Fetch just enough info for the enumeration
  1164. //
  1165. m_dwMDUserType = IIS_MD_UT_SERVER;
  1166. m_dwInstance = CMetabasePath::GetInstanceNumber(lpszMDPath);
  1167. }
  1168. CInstanceProps::CInstanceProps(
  1169. IN CMetaInterface * pInterface,
  1170. IN LPCTSTR lpszMDPath,
  1171. IN UINT nDefPort OPTIONAL
  1172. )
  1173. /*++
  1174. Routine Description:
  1175. Constructor that uses an existing interface
  1176. Arguments:
  1177. CMetaInterface * pInterface : Existing interface
  1178. LPCTSTR lpszMDPath : Metabase path
  1179. UINT nDefPort : Default port
  1180. Return Value:
  1181. N/A
  1182. --*/
  1183. : CMetaProperties(pInterface, lpszMDPath),
  1184. m_dwWin32Error(ERROR_SUCCESS),
  1185. //
  1186. // Default Instance Values
  1187. //
  1188. m_strlBindings(),
  1189. m_strComment(),
  1190. m_fCluster(FALSE),
  1191. m_nTCPPort(nDefPort),
  1192. m_iaIpAddress((DWORD)0),
  1193. m_strDomainName(),
  1194. m_dwState(MD_SERVER_STATE_STOPPED)
  1195. {
  1196. //
  1197. // Fetch enough for enumeration only
  1198. //
  1199. m_dwMDUserType = IIS_MD_UT_SERVER;
  1200. m_dwInstance = CMetabasePath::GetInstanceNumber(lpszMDPath);
  1201. }
  1202. CInstanceProps::CInstanceProps(
  1203. IN CMetaKey * pKey,
  1204. IN LPCTSTR lpszMDPath, OPTIONAL
  1205. IN DWORD dwInstance,
  1206. IN UINT nDefPort OPTIONAL
  1207. )
  1208. /*++
  1209. Routine Description:
  1210. Read instance properties off an open parent key
  1211. Arguments:
  1212. CMetaKey * pKey : Open key (parent node)
  1213. LPCTSTR lpszMDPath : Relative instance path off the open key
  1214. DWORD dwInstance : Instance number (0 for master instance)
  1215. UINT nDefPort : Default port number
  1216. Return Value:
  1217. N/A
  1218. --*/
  1219. : CMetaProperties(pKey, lpszMDPath),
  1220. m_dwInstance(dwInstance),
  1221. m_dwWin32Error(ERROR_SUCCESS),
  1222. //
  1223. // Default Instance Values
  1224. //
  1225. m_strlBindings(),
  1226. m_strComment(),
  1227. m_fCluster(FALSE),
  1228. m_nTCPPort(nDefPort),
  1229. m_iaIpAddress((DWORD)0),
  1230. m_strDomainName(),
  1231. m_dwState(MD_SERVER_STATE_STOPPED)
  1232. {
  1233. //
  1234. // Fetch enough for enumeration only
  1235. //
  1236. m_dwMDUserType = IIS_MD_UT_SERVER;
  1237. }
  1238. /* virtual */
  1239. void
  1240. CInstanceProps::ParseFields()
  1241. /*++
  1242. Routine Description:
  1243. Break into fields.
  1244. Arguments:
  1245. None.
  1246. Return Value:
  1247. None.
  1248. --*/
  1249. {
  1250. BEGIN_PARSE_META_RECORDS(m_dwNumEntries, m_pbMDData)
  1251. HANDLE_META_RECORD(MD_SERVER_BINDINGS, m_strlBindings)
  1252. HANDLE_META_RECORD(MD_SERVER_COMMENT, m_strComment)
  1253. HANDLE_META_RECORD(MD_SERVER_STATE, m_dwState)
  1254. HANDLE_META_RECORD(MD_WIN32_ERROR, m_dwWin32Error);
  1255. HANDLE_META_RECORD(MD_CLUSTER_ENABLED, m_fCluster);
  1256. END_PARSE_META_RECORDS
  1257. //
  1258. // Crack the primary binding
  1259. //
  1260. if (MP_V(m_strlBindings).GetCount() > 0)
  1261. {
  1262. CString & strBinding = MP_V(m_strlBindings).GetHead();
  1263. CrackBinding(strBinding, m_iaIpAddress, m_nTCPPort, m_strDomainName);
  1264. }
  1265. }
  1266. /* virtual */
  1267. HRESULT
  1268. CInstanceProps::WriteDirtyProps()
  1269. /*++
  1270. Routine Description:
  1271. Write the dirty properties to the metabase
  1272. Arguments:
  1273. None
  1274. Return Value:
  1275. HRESULT
  1276. --*/
  1277. {
  1278. CError err;
  1279. BEGIN_META_WRITE()
  1280. META_WRITE(MD_SERVER_BINDINGS, m_strlBindings)
  1281. META_WRITE(MD_SERVER_COMMENT, m_strComment)
  1282. META_WRITE(MD_SERVER_STATE, m_dwState)
  1283. END_META_WRITE(err);
  1284. return err;
  1285. }
  1286. HRESULT
  1287. CInstanceProps::ChangeState(
  1288. IN DWORD dwCommand
  1289. )
  1290. /*++
  1291. Routine Description:
  1292. Change the state of the instance
  1293. Arguments:
  1294. DWORD dwCommand : Command
  1295. Return Value:
  1296. HRESULT
  1297. --*/
  1298. {
  1299. DWORD dwTargetState;
  1300. DWORD dwPendingState;
  1301. CError err;
  1302. switch(dwCommand)
  1303. {
  1304. case MD_SERVER_COMMAND_STOP:
  1305. dwTargetState = MD_SERVER_STATE_STOPPED;
  1306. dwPendingState = MD_SERVER_STATE_STOPPING;
  1307. break;
  1308. case MD_SERVER_COMMAND_START:
  1309. dwTargetState = MD_SERVER_STATE_STARTED;
  1310. dwPendingState = (m_dwState == MD_SERVER_STATE_PAUSED)
  1311. ? MD_SERVER_STATE_CONTINUING
  1312. : MD_SERVER_STATE_STARTING;
  1313. break;
  1314. case MD_SERVER_COMMAND_CONTINUE:
  1315. dwTargetState = MD_SERVER_STATE_STARTED;
  1316. dwPendingState = MD_SERVER_STATE_CONTINUING;
  1317. break;
  1318. case MD_SERVER_COMMAND_PAUSE:
  1319. dwTargetState = MD_SERVER_STATE_PAUSED;
  1320. dwPendingState = MD_SERVER_STATE_PAUSING;
  1321. break;
  1322. default:
  1323. ASSERT_MSG("Invalid service state requested");
  1324. err = ERROR_INVALID_PARAMETER;
  1325. }
  1326. err = OpenForWriting(FALSE);
  1327. if (err.Succeeded())
  1328. {
  1329. SetValue(MD_WIN32_ERROR, m_dwWin32Error = 0);
  1330. err = SetValue(MD_SERVER_COMMAND, dwCommand);
  1331. Close();
  1332. }
  1333. if (err.Succeeded())
  1334. {
  1335. //
  1336. // Wait for the service to attain desired state, timeout
  1337. // after specified interval
  1338. //
  1339. DWORD dwSleepTotal = 0L;
  1340. DWORD dwOldState = m_dwState;
  1341. if (dwOldState == dwTargetState)
  1342. {
  1343. //
  1344. // Current state matches desired
  1345. // state already. ISM must be behind
  1346. // the times.
  1347. //
  1348. return err;
  1349. }
  1350. while (dwSleepTotal < MAX_SLEEP_INST)
  1351. {
  1352. err = LoadData();
  1353. if (err.Failed())
  1354. {
  1355. break;
  1356. }
  1357. if ((m_dwState != dwPendingState && m_dwState != dwOldState)
  1358. || m_dwWin32Error != ERROR_SUCCESS
  1359. )
  1360. {
  1361. //
  1362. // Done one way or another
  1363. //
  1364. if (m_dwState != dwTargetState)
  1365. {
  1366. //
  1367. // Did not achieve desired result. Something went
  1368. // wrong.
  1369. //
  1370. if (m_dwWin32Error)
  1371. {
  1372. err = m_dwWin32Error;
  1373. }
  1374. }
  1375. break;
  1376. }
  1377. //
  1378. // Still pending...
  1379. //
  1380. ::Sleep(SLEEP_INTERVAL);
  1381. dwSleepTotal += SLEEP_INTERVAL;
  1382. }
  1383. if (dwSleepTotal >= MAX_SLEEP_INST)
  1384. {
  1385. //
  1386. // Timed out. If there is a real error in the metabase
  1387. // use it, otherwise use a generic timeout error
  1388. //
  1389. err = m_dwWin32Error;
  1390. if (err.Succeeded())
  1391. {
  1392. err = ERROR_SERVICE_REQUEST_TIMEOUT;
  1393. }
  1394. }
  1395. }
  1396. return err;
  1397. }
  1398. /* static */
  1399. HRESULT
  1400. CInstanceProps::Add(
  1401. CMetaInterface * pInterface,
  1402. LPCTSTR lpszService,
  1403. LPCTSTR lpszHomePath,
  1404. LPCTSTR lpszUserName,
  1405. LPCTSTR lpszPassword,
  1406. LPCTSTR lpszDescription,
  1407. LPCTSTR lpszBinding,
  1408. LPCTSTR lpszSecureBinding,
  1409. DWORD * pdwPermissions,
  1410. DWORD * pdwDirBrowsing,
  1411. DWORD * pwdAuthFlags,
  1412. DWORD * pdwInstance
  1413. )
  1414. /*++
  1415. Routine Description:
  1416. Create a new instance. Find a free instance number, and attempt
  1417. to create it. Optionally return the new instance number.
  1418. Arguments:
  1419. const CMetaInterface * pInterface : Existing interface
  1420. LPCTSTR lpszService : Service name
  1421. LPCTSTR lpszHomePath : physical path for the new home directory
  1422. LPCTSTR lpszUserName : User name
  1423. LPCTSTR lpszPassword : Password
  1424. LPCTSTR lpszDescription : Optional instance description.
  1425. LPCTSTR lpszBinding : Binding string
  1426. LPCTSTR lpszSecureBinding : Secure binding string
  1427. DWORD * pdwPermission : Permission bits
  1428. DWORD * pdwDirBrowsing : Directory browsing
  1429. DWORD * pwdAuthFlags : Authorization flags
  1430. DWORD * pdwInstance : Buffer to the new instance number
  1431. Return Value:
  1432. HRESULT
  1433. --*/
  1434. {
  1435. CError err;
  1436. DWORD inst = 0;
  1437. DWORD RequestedSiteInst = 0;
  1438. TCHAR bind[MAX_PATH];
  1439. BOOL bRegistryKeyExists = FALSE;
  1440. // this functionality is keyed off of a registry key
  1441. // if it exists and is set to 1 then use the old way..
  1442. DWORD rc, size, type;
  1443. HKEY hkey;
  1444. err = RegOpenKey(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\Microsoft\\InetMgr\\Parameters"), &hkey);
  1445. if (err == ERROR_SUCCESS)
  1446. {
  1447. size = sizeof(DWORD);
  1448. if (ERROR_SUCCESS == RegQueryValueEx(hkey,_T("IncrementalSiteIDCreation"),0,&type,(LPBYTE)&rc,&size))
  1449. {
  1450. if (type == REG_DWORD)
  1451. {
  1452. if (rc == 1)
  1453. {
  1454. bRegistryKeyExists = TRUE;
  1455. }
  1456. }
  1457. }
  1458. RegCloseKey(hkey);
  1459. }
  1460. if (lpszBinding != NULL)
  1461. {
  1462. int len = lstrlen(lpszBinding);
  1463. if (len < (MAX_PATH - 2))
  1464. {
  1465. StrCpyN(bind, lpszBinding, MAX_PATH - 2);
  1466. bind[len+1] = 0;
  1467. }
  1468. else
  1469. {
  1470. return ERROR_INVALID_PARAMETER;
  1471. }
  1472. }
  1473. if (bRegistryKeyExists)
  1474. {
  1475. CMetaKey mk(
  1476. pInterface,
  1477. CMetabasePath(lpszService),
  1478. METADATA_PERMISSION_READ | METADATA_PERMISSION_WRITE
  1479. );
  1480. err = mk.QueryResult();
  1481. //
  1482. // Loop through until we find a free instance number. This
  1483. // is not ideal, but the only way to do this for now.
  1484. //
  1485. CString strPath;
  1486. LPTSTR lp = strPath.GetBuffer(MAX_INSTANCE_LEN);
  1487. for (DWORD dw = FIRST_INSTANCE; dw <= LAST_INSTANCE; ++dw)
  1488. {
  1489. ::_ultot(dw, lp, 10);
  1490. err = mk.DoesPathExist(lp);
  1491. if (err.Failed())
  1492. {
  1493. if (err.Win32Error() != ERROR_PATH_NOT_FOUND)
  1494. {
  1495. //
  1496. // Unexpected error
  1497. //
  1498. return err;
  1499. }
  1500. strPath.ReleaseBuffer();
  1501. // request to use this instance number
  1502. RequestedSiteInst = dw;
  1503. break;
  1504. // we don't need to do the below
  1505. // behavior since we will just be "requesting"
  1506. // an ID and if the id is already taken
  1507. // it will just give us a random one...
  1508. /*
  1509. err = mk.AddKey(strPath);
  1510. if (err.Succeeded())
  1511. {
  1512. err = mk.DeleteKey(strPath);
  1513. if (err.Succeeded())
  1514. {
  1515. //
  1516. // request to use this instance number
  1517. //
  1518. RequestedSiteInst = dw;
  1519. break;
  1520. }
  1521. }
  1522. */
  1523. }
  1524. }
  1525. mk.Close();
  1526. err = pInterface->CreateSite(lpszService, lpszDescription, bind, lpszHomePath, &inst, &RequestedSiteInst);
  1527. }
  1528. else
  1529. {
  1530. err = pInterface->CreateSite(lpszService, lpszDescription, bind, lpszHomePath, &inst);
  1531. }
  1532. if (err.Succeeded())
  1533. {
  1534. CMetaKey mk(pInterface, CMetabasePath(lpszService), METADATA_PERMISSION_WRITE);
  1535. err = mk.QueryResult();
  1536. if (err.Failed())
  1537. {
  1538. ASSERT(FALSE);
  1539. return err;
  1540. }
  1541. if (pdwInstance)
  1542. {
  1543. *pdwInstance = inst;
  1544. }
  1545. CString inst_path, root_path;
  1546. wnsprintf(inst_path.GetBuffer(MAX_PATH), MAX_PATH, _T("%d"), inst);
  1547. inst_path.ReleaseBuffer();
  1548. root_path = inst_path;
  1549. root_path += SZ_MBN_SEP_STR;
  1550. root_path += SZ_MBN_ROOT;
  1551. //
  1552. // The service binding
  1553. //
  1554. //if (err.Succeeded() && lpszBinding)
  1555. //{
  1556. // CString strBinding(lpszBinding);
  1557. // CStringListEx strlBindings;
  1558. // strlBindings.AddTail(strBinding);
  1559. // err = mk.SetValue(MD_SERVER_BINDINGS, strlBindings,
  1560. // NULL, inst_path);
  1561. //}
  1562. //
  1563. // The secure binding
  1564. //
  1565. if (err.Succeeded() && lpszSecureBinding && *lpszSecureBinding != 0)
  1566. {
  1567. CString strBinding(lpszSecureBinding);
  1568. CStringListEx strlBindings;
  1569. strlBindings.AddTail(strBinding);
  1570. err = mk.SetValue(MD_SECURE_BINDINGS, strlBindings,
  1571. NULL, inst_path);
  1572. }
  1573. //
  1574. // Now add the home directory for it
  1575. //
  1576. //if (err.Succeeded())
  1577. //{
  1578. // CString strHomePath(lpszHomePath);
  1579. // err = mk.SetValue(MD_VR_PATH, strHomePath, NULL, root_path);
  1580. //}
  1581. if (err.Succeeded() && pwdAuthFlags)
  1582. {
  1583. err = mk.SetValue(MD_AUTHORIZATION, *pwdAuthFlags, NULL, root_path);
  1584. }
  1585. if (err.Succeeded() && lpszUserName != NULL)
  1586. {
  1587. ASSERT_PTR(lpszPassword);
  1588. CString strUserName(lpszUserName);
  1589. err = mk.SetValue(MD_VR_USERNAME, strUserName, NULL, root_path);
  1590. }
  1591. if (err.Succeeded() && lpszPassword != NULL)
  1592. {
  1593. ASSERT_PTR(lpszUserName);
  1594. CString strPassword(lpszPassword);
  1595. err = mk.SetValue(MD_VR_PASSWORD, strPassword, NULL, root_path);
  1596. }
  1597. if (err.Succeeded() && pdwPermissions != NULL)
  1598. {
  1599. err = mk.SetValue(MD_ACCESS_PERM, *pdwPermissions, NULL, root_path);
  1600. }
  1601. if (err.Succeeded() && pdwDirBrowsing != NULL)
  1602. {
  1603. //
  1604. // WWW only
  1605. //
  1606. err = mk.SetValue(MD_DIRECTORY_BROWSING, *pdwDirBrowsing, NULL, root_path);
  1607. }
  1608. }
  1609. return err;
  1610. }
  1611. /* static */
  1612. HRESULT
  1613. CInstanceProps::Delete(
  1614. IN CMetaInterface * pInterface,
  1615. IN LPCTSTR lpszService,
  1616. IN DWORD dwInstance
  1617. )
  1618. /*++
  1619. Routine Description:
  1620. Delete the given instance number
  1621. Arguments:
  1622. LPCTSTR lpszServer : Server name
  1623. LPCTSTR lpszService : Service name (e.g. W3SVC)
  1624. DWORD dwInstance : Instance number to be deleted
  1625. Return Value:
  1626. HRESULT
  1627. --*/
  1628. {
  1629. CMetaKey mk(
  1630. pInterface,
  1631. CMetabasePath(lpszService),
  1632. NULL,
  1633. METADATA_PERMISSION_WRITE
  1634. );
  1635. CError err(mk.QueryResult());
  1636. if (err.Failed())
  1637. {
  1638. return err;
  1639. }
  1640. CString strPath;
  1641. LPTSTR lp = strPath.GetBuffer(MAX_INSTANCE_LEN);
  1642. ::_ltot(dwInstance, lp, 10);
  1643. strPath.ReleaseBuffer();
  1644. err = mk.DeleteKey(strPath);
  1645. return err;
  1646. }
  1647. //
  1648. // Child node properties
  1649. //
  1650. // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  1651. //
  1652. // Redirect tags
  1653. //
  1654. const TCHAR CChildNodeProps::_chTagSep = _T(',');
  1655. const LPCTSTR CChildNodeProps::_cszExactDestination = _T("EXACT_DESTINATION");
  1656. const LPCTSTR CChildNodeProps::_cszChildOnly = _T("CHILD_ONLY");
  1657. const LPCTSTR CChildNodeProps::_cszPermanent = _T("PERMANENT");
  1658. CChildNodeProps::CChildNodeProps(
  1659. IN CComAuthInfo * pAuthInfo,
  1660. IN LPCTSTR lpszMDPath,
  1661. IN BOOL fInherit, OPTIONAL
  1662. IN BOOL fPathOnly OPTIONAL
  1663. )
  1664. /*++
  1665. Routine Description:
  1666. Child node properties (Can be file, dir, or vdir)
  1667. Arguments:
  1668. CComAuthInfo * pAuthInfo : Authentication info
  1669. LPCTSTR lpszMDPath : Metabase path
  1670. BOOL fInherit : TRUE to inherit values, FALSE otherwise
  1671. BOOL fPathOnly : TRUE to only fetch the path
  1672. Return Value:
  1673. N/A
  1674. --*/
  1675. : CMetaProperties(
  1676. pAuthInfo,
  1677. lpszMDPath
  1678. ),
  1679. m_strRedirectStatement(),
  1680. m_strFullMetaPath(lpszMDPath),
  1681. m_strRedirectPath(),
  1682. m_fExact(FALSE),
  1683. m_fChild(FALSE),
  1684. m_fPermanent(FALSE),
  1685. m_dwAccessPerms(0L),
  1686. m_dwDirBrowsing(0L),
  1687. m_dwWin32Error(ERROR_SUCCESS),
  1688. m_fIsAppRoot(FALSE),
  1689. m_fAppIsolated(FALSE),
  1690. //
  1691. // Default properties
  1692. //
  1693. m_fPathInherited(FALSE),
  1694. m_strPath()
  1695. {
  1696. if (fPathOnly)
  1697. {
  1698. //
  1699. // Fetch only the homeroot physical path
  1700. //
  1701. m_dwMDUserType = IIS_MD_UT_FILE;
  1702. m_dwMDDataType = STRING_METADATA;
  1703. }
  1704. //
  1705. // Override base parameters
  1706. //
  1707. m_fInherit = fInherit;
  1708. CMetabasePath::GetLastNodeName(lpszMDPath, m_strAlias);
  1709. }
  1710. CChildNodeProps::CChildNodeProps(
  1711. IN CMetaInterface * pInterface,
  1712. IN LPCTSTR lpszMDPath,
  1713. IN BOOL fInherit, OPTIONAL
  1714. IN BOOL fPathOnly OPTIONAL
  1715. )
  1716. /*++
  1717. Routine Description:
  1718. Child node properties (Can be file, dir, or vdir)
  1719. Arguments:
  1720. CMetaInterface * pInterface : Existing interface
  1721. LPCTSTR lpszMDPath : Metabase path
  1722. BOOL fInherit : TRUE to inherit values, FALSE otherwise
  1723. BOOL fPathOnly : TRUE to only fetch the path
  1724. Return Value:
  1725. N/A
  1726. --*/
  1727. : CMetaProperties(
  1728. pInterface,
  1729. lpszMDPath
  1730. ),
  1731. m_strRedirectStatement(),
  1732. m_strFullMetaPath(lpszMDPath),
  1733. m_strRedirectPath(),
  1734. m_fExact(FALSE),
  1735. m_fChild(FALSE),
  1736. m_fPermanent(FALSE),
  1737. m_dwAccessPerms(0L),
  1738. m_dwDirBrowsing(0L),
  1739. m_dwWin32Error(ERROR_SUCCESS),
  1740. m_fIsAppRoot(FALSE),
  1741. m_fAppIsolated(FALSE),
  1742. //
  1743. // Default properties
  1744. //
  1745. m_fPathInherited(FALSE),
  1746. m_strPath()
  1747. {
  1748. if (fPathOnly)
  1749. {
  1750. //
  1751. // Fetch only the homeroot physical path
  1752. //
  1753. m_dwMDUserType = IIS_MD_UT_FILE;
  1754. m_dwMDDataType = STRING_METADATA;
  1755. }
  1756. //
  1757. // Override base parameters
  1758. //
  1759. m_fInherit = fInherit;
  1760. CMetabasePath::GetLastNodeName(lpszMDPath, m_strAlias);
  1761. }
  1762. CChildNodeProps::CChildNodeProps(
  1763. IN CMetaKey * pKey,
  1764. IN LPCTSTR lpszMDPath, OPTIONAL
  1765. IN BOOL fInherit, OPTIONAL
  1766. IN BOOL fPathOnly OPTIONAL
  1767. )
  1768. /*++
  1769. Routine Description:
  1770. Construct from open key
  1771. Arguments:
  1772. const CMetaKey * pKey Open key
  1773. LPCTSTR lpszMDPath Path
  1774. BOOL fInherit TRUE to inherit properties
  1775. BOOL fPathOnly TRUE to only fetch the path
  1776. Return Value:
  1777. N/A
  1778. --*/
  1779. : CMetaProperties(pKey, lpszMDPath),
  1780. m_strRedirectStatement(),
  1781. m_strFullMetaPath(),
  1782. m_strRedirectPath(),
  1783. m_fExact(FALSE),
  1784. m_fChild(FALSE),
  1785. m_fPermanent(FALSE),
  1786. m_dwAccessPerms(0L),
  1787. m_dwDirBrowsing(0L),
  1788. m_dwWin32Error(ERROR_SUCCESS),
  1789. m_fIsAppRoot(FALSE),
  1790. m_fAppIsolated(FALSE),
  1791. //
  1792. // Default properties
  1793. //
  1794. m_fPathInherited(FALSE),
  1795. m_strPath()
  1796. {
  1797. if (fPathOnly)
  1798. {
  1799. ASSERT(FALSE);
  1800. m_dwMDUserType = IIS_MD_UT_FILE;
  1801. m_dwMDDataType = STRING_METADATA;
  1802. }
  1803. else
  1804. {
  1805. //
  1806. // Build full metabase path, because we need to compare it
  1807. // against the app root path
  1808. //
  1809. CMetabasePath path(FALSE, pKey->QueryMetaPath(), lpszMDPath);
  1810. m_strFullMetaPath = path.QueryMetaPath();
  1811. }
  1812. //
  1813. // Override base parameters
  1814. //
  1815. m_fInherit = fInherit;
  1816. CMetabasePath::GetLastNodeName(m_strFullMetaPath, m_strAlias);
  1817. }
  1818. void
  1819. CChildNodeProps::ParseRedirectStatement()
  1820. /*++
  1821. Routine Description:
  1822. Break down the redirect statement into its component parts (path
  1823. plus directives)
  1824. Arguments:
  1825. None
  1826. Return Value:
  1827. None
  1828. --*/
  1829. {
  1830. m_fExact = FALSE;
  1831. m_fChild = FALSE;
  1832. m_fPermanent = FALSE;
  1833. m_strRedirectPath = m_strRedirectStatement;
  1834. int nComma = m_strRedirectPath.Find(_chTagSep);
  1835. if (nComma >= 0)
  1836. {
  1837. //
  1838. // Check past the separator for these tags
  1839. //
  1840. LPCTSTR lpstr = m_strRedirectPath;
  1841. lpstr += (nComma + 1);
  1842. m_fExact = _tcsstr(lpstr, _cszExactDestination) != NULL;
  1843. m_fChild = _tcsstr(lpstr, _cszChildOnly) != NULL;
  1844. m_fPermanent = _tcsstr(lpstr, _cszPermanent) != NULL;
  1845. m_strRedirectPath.ReleaseBuffer(nComma);
  1846. }
  1847. }
  1848. void
  1849. CChildNodeProps::BuildRedirectStatement()
  1850. /*++
  1851. Routine Description:
  1852. Assemble the redirect statement from its component parts (path
  1853. plus directives)
  1854. Arguments:
  1855. None
  1856. Return Value:
  1857. None
  1858. --*/
  1859. {
  1860. CString strStatement = m_strRedirectPath;
  1861. ASSERT(strStatement.Find(_chTagSep) < 0);
  1862. if (m_fExact)
  1863. {
  1864. strStatement += _chTagSep;
  1865. strStatement += _T(' ');
  1866. strStatement += _cszExactDestination;
  1867. }
  1868. if (m_fChild)
  1869. {
  1870. strStatement += _chTagSep;
  1871. strStatement += _T(' ');
  1872. strStatement += _cszChildOnly;
  1873. }
  1874. if (m_fPermanent)
  1875. {
  1876. strStatement += _chTagSep;
  1877. strStatement += _T(' ');
  1878. strStatement += _cszPermanent;
  1879. }
  1880. m_strRedirectStatement = strStatement;
  1881. }
  1882. /* virtual */
  1883. void
  1884. CChildNodeProps::ParseFields()
  1885. /*++
  1886. Routine Description:
  1887. Break into fields.
  1888. Arguments:
  1889. None.
  1890. Return Value:
  1891. None.
  1892. --*/
  1893. {
  1894. BEGIN_PARSE_META_RECORDS(m_dwNumEntries, m_pbMDData)
  1895. HANDLE_INHERITED_META_RECORD(MD_VR_PATH, m_strPath, m_fPathInherited)
  1896. HANDLE_META_RECORD(MD_HTTP_REDIRECT, m_strRedirectStatement)
  1897. HANDLE_META_RECORD(MD_WIN32_ERROR, m_dwWin32Error)
  1898. HANDLE_META_RECORD(MD_ACCESS_PERM, m_dwAccessPerms)
  1899. HANDLE_META_RECORD(MD_DIRECTORY_BROWSING, m_dwDirBrowsing)
  1900. HANDLE_META_RECORD(MD_APP_ROOT, m_strAppRoot)
  1901. HANDLE_META_RECORD(MD_APP_ISOLATED, m_fAppIsolated)
  1902. END_PARSE_META_RECORDS
  1903. //
  1904. // Check to see if this is an application root
  1905. //
  1906. if (!MP_V(m_strAppRoot).IsEmpty())
  1907. {
  1908. TRACEEOLID("App root: " << m_strAppRoot);
  1909. m_fIsAppRoot = m_strFullMetaPath.CompareNoCase(m_strAppRoot) == 0;
  1910. // m_fIsAppRoot = m_strMetaRoot.CompareNoCase(m_strAppRoot) == 0;
  1911. }
  1912. //
  1913. // Break down redirect statement into component parts
  1914. //
  1915. ParseRedirectStatement();
  1916. }
  1917. /* virtual */
  1918. HRESULT
  1919. CChildNodeProps::WriteDirtyProps()
  1920. /*++
  1921. Routine Description:
  1922. Write the dirty properties to the metabase
  1923. Arguments:
  1924. None
  1925. Return Value:
  1926. HRESULT
  1927. --*/
  1928. {
  1929. CError err;
  1930. BEGIN_META_WRITE()
  1931. META_WRITE(MD_VR_PATH, m_strPath)
  1932. META_WRITE(MD_ACCESS_PERM, m_dwAccessPerms)
  1933. META_WRITE(MD_DIRECTORY_BROWSING, m_dwDirBrowsing)
  1934. if (IsRedirected())
  1935. {
  1936. //
  1937. // (Re-)Assemble the redirect statement from its component parts
  1938. //
  1939. BuildRedirectStatement();
  1940. META_WRITE_INHERITANCE(MD_HTTP_REDIRECT, m_strRedirectStatement, m_fInheritRedirect)
  1941. }
  1942. else
  1943. {
  1944. // If m_strRedirectPath is empty, but redir statement is not empty,
  1945. // then redirection was just removed, we should delete it dirty or not
  1946. if (!((CString)m_strRedirectStatement).IsEmpty())
  1947. {
  1948. META_DELETE(MD_HTTP_REDIRECT)
  1949. }
  1950. }
  1951. END_META_WRITE(err);
  1952. return err;
  1953. }
  1954. /* static */
  1955. HRESULT
  1956. CChildNodeProps::Add(
  1957. IN CMetaInterface * pInterface,
  1958. IN LPCTSTR lpszParentPath,
  1959. IN LPCTSTR lpszAlias,
  1960. OUT CString & strAliasCreated,
  1961. IN DWORD * pdwPermissions, OPTIONAL
  1962. IN DWORD * pdwDirBrowsing, OPTIONAL
  1963. IN LPCTSTR lpszVrPath, OPTIONAL
  1964. IN LPCTSTR lpszUserName, OPTIONAL
  1965. IN LPCTSTR lpszPassword, OPTIONAL
  1966. IN BOOL fExactName
  1967. )
  1968. /*++
  1969. Routine Description:
  1970. Create new child node. Optionally, this will append a number
  1971. to the alias name to ensure uniqueness
  1972. Arguments:
  1973. const CMetaInterface * pInterface : Existing interface
  1974. LPCTSTR lpszParentPath : Parent path
  1975. DWORD dwInstance : Instance number (could be MASTER_INSTANCE)
  1976. LPCTSTR lpszVrPath : VrPath property
  1977. LPCTSTR lpszUserName : User name
  1978. LPCTSTR lpszPassword : Password
  1979. BOOL fExactName : If TRUE, do not change the name
  1980. to enforce uniqueness.
  1981. Return Value:
  1982. HRESULT
  1983. --*/
  1984. {
  1985. CMetaKey mk(pInterface);
  1986. CError err(mk.QueryResult());
  1987. if (err.Failed())
  1988. {
  1989. //
  1990. // Hopeless...
  1991. //
  1992. return err;
  1993. }
  1994. BOOL fNewPath;
  1995. do
  1996. {
  1997. fNewPath = FALSE;
  1998. err = mk.Open(
  1999. METADATA_PERMISSION_WRITE | METADATA_PERMISSION_READ,
  2000. lpszParentPath
  2001. /*
  2002. lpszService,
  2003. dwInstance,
  2004. lpszParentPath
  2005. */
  2006. );
  2007. if (err.Win32Error() == ERROR_PATH_NOT_FOUND)
  2008. {
  2009. //
  2010. // This could happen -- creating a virtual
  2011. // server underneath a physical directory
  2012. // which does not exist in the metabase.
  2013. //
  2014. CString strParent, strAlias;
  2015. CMetabasePath::SplitMetaPathAtInstance(lpszParentPath, strParent, strAlias);
  2016. err = mk.Open(
  2017. METADATA_PERMISSION_WRITE,
  2018. strParent
  2019. //lpszParentPath
  2020. //lpszService,
  2021. //dwInstance
  2022. );
  2023. if (err.Failed())
  2024. {
  2025. //
  2026. // This really should never fail, because we're opening
  2027. // the path at the instance.
  2028. //
  2029. ASSERT_MSG("Instance path does not exist");
  2030. break;
  2031. }
  2032. //err = mk.AddKey(lpszParentPath);
  2033. err = mk.AddKey(strAlias);
  2034. fNewPath = err.Succeeded();
  2035. mk.Close();
  2036. }
  2037. }
  2038. while(fNewPath);
  2039. if (err.Failed())
  2040. {
  2041. return err;
  2042. }
  2043. strAliasCreated = lpszAlias;
  2044. DWORD dw = 2;
  2045. FOREVER
  2046. {
  2047. //
  2048. // Append a number if the name is not unique.
  2049. //
  2050. err = mk.DoesPathExist(strAliasCreated);
  2051. if (err.Failed())
  2052. {
  2053. if (err.Win32Error() != ERROR_PATH_NOT_FOUND)
  2054. {
  2055. //
  2056. // Unexpected error
  2057. //
  2058. return err;
  2059. }
  2060. //
  2061. // Ok, now create it
  2062. //
  2063. err = mk.AddKey(strAliasCreated);
  2064. if (err.Succeeded())
  2065. {
  2066. CString strKeyName;
  2067. CString buf, service;
  2068. CMetabasePath::GetServicePath(lpszParentPath, buf);
  2069. CMetabasePath::GetLastNodeName(buf, service);
  2070. if (0 == service.CompareNoCase(SZ_MBN_WEB))
  2071. {
  2072. strKeyName = IIS_CLASS_WEB_VDIR_W;
  2073. }
  2074. else if (0 == service.CompareNoCase(SZ_MBN_FTP))
  2075. {
  2076. strKeyName = IIS_CLASS_FTP_VDIR_W;
  2077. }
  2078. else
  2079. {
  2080. ASSERT_MSG("unrecognized service name");
  2081. }
  2082. err = mk.SetValue(
  2083. MD_KEY_TYPE,
  2084. strKeyName,
  2085. NULL,
  2086. strAliasCreated
  2087. );
  2088. if (lpszVrPath != NULL)
  2089. {
  2090. CString strVrPath(lpszVrPath);
  2091. err = mk.SetValue(
  2092. MD_VR_PATH,
  2093. strVrPath,
  2094. NULL,
  2095. strAliasCreated
  2096. );
  2097. }
  2098. if (lpszUserName != NULL)
  2099. {
  2100. ASSERT_PTR(lpszPassword);
  2101. CString strUserName(lpszUserName);
  2102. err = mk.SetValue(
  2103. MD_VR_USERNAME,
  2104. strUserName,
  2105. NULL,
  2106. strAliasCreated
  2107. );
  2108. }
  2109. if (lpszPassword != NULL)
  2110. {
  2111. ASSERT_PTR(lpszUserName);
  2112. CString strPassword(lpszPassword);
  2113. err = mk.SetValue(
  2114. MD_VR_PASSWORD,
  2115. strPassword,
  2116. NULL,
  2117. strAliasCreated
  2118. );
  2119. }
  2120. if (pdwPermissions != NULL)
  2121. {
  2122. err = mk.SetValue(
  2123. MD_ACCESS_PERM,
  2124. *pdwPermissions,
  2125. NULL,
  2126. strAliasCreated
  2127. );
  2128. }
  2129. if (pdwDirBrowsing != NULL)
  2130. {
  2131. //
  2132. // WWW only
  2133. //
  2134. err = mk.SetValue(
  2135. MD_DIRECTORY_BROWSING,
  2136. *pdwDirBrowsing,
  2137. NULL,
  2138. strAliasCreated
  2139. );
  2140. }
  2141. }
  2142. return err;
  2143. }
  2144. //
  2145. // Name is not unique, increase the number and try
  2146. // again if permitted to so. Otherwise return the
  2147. // 'path exists' error.
  2148. //
  2149. if (fExactName)
  2150. {
  2151. err = ERROR_ALREADY_EXISTS;
  2152. return err;
  2153. }
  2154. TCHAR szNumber[32];
  2155. ::_ultot(dw++, szNumber, 10);
  2156. strAliasCreated = lpszAlias;
  2157. strAliasCreated += szNumber;
  2158. //
  2159. // Continue on...
  2160. //
  2161. }
  2162. }
  2163. /* static */
  2164. HRESULT
  2165. CChildNodeProps::Delete(
  2166. IN CMetaInterface * pInterface,
  2167. IN LPCTSTR lpszParentPath, OPTIONAL
  2168. IN LPCTSTR lpszNode
  2169. )
  2170. /*++
  2171. Routine Description:
  2172. Delete child node off the given parent path
  2173. Arguments:
  2174. const CMetaInterface * pInterface, Existing interface
  2175. LPCTSTR lpszParentPath : Parent path (could be NULL)
  2176. LPCTSTR lpszNode : Name of node to be deleted
  2177. Return Value:
  2178. HRESULT
  2179. --*/
  2180. {
  2181. CMetaKey mk(
  2182. pInterface,
  2183. lpszParentPath,
  2184. METADATA_PERMISSION_WRITE
  2185. );
  2186. CError err(mk.QueryResult());
  2187. if (err.Failed())
  2188. {
  2189. return err;
  2190. }
  2191. err = mk.DeleteKey(lpszNode);
  2192. return err;
  2193. }
  2194. /* static */
  2195. HRESULT
  2196. CChildNodeProps::Rename(
  2197. IN CMetaInterface * pInterface,
  2198. IN LPCTSTR lpszParentPath, OPTIONAL
  2199. IN LPCTSTR lpszOldName,
  2200. IN LPCTSTR lpszNewName
  2201. )
  2202. /*++
  2203. Routine Description:
  2204. Rename a child node off the given path
  2205. Arguments:
  2206. IN const CMetaInterface * pInterface : Existing interface
  2207. LPCTSTR lpszParentPath : Parent path (could be NULL)
  2208. LPCTSTR lpszOldName : Old node name
  2209. LPCTSTR lpszNewName : New node name
  2210. Return Value:
  2211. HRESULT
  2212. --*/
  2213. {
  2214. CMetaKey mk(
  2215. pInterface,
  2216. lpszParentPath,
  2217. METADATA_PERMISSION_WRITE
  2218. );
  2219. CError err(mk.QueryResult());
  2220. if (err.Failed())
  2221. {
  2222. return err;
  2223. }
  2224. err = mk.RenameKey(lpszOldName, lpszNewName);
  2225. mk.Close();
  2226. if (err.Succeeded())
  2227. {
  2228. CString strNewPath;
  2229. strNewPath = lpszParentPath;
  2230. strNewPath += SZ_MBN_SEP_STR;
  2231. strNewPath += lpszNewName;
  2232. CMetaKey mk2(
  2233. pInterface,
  2234. strNewPath,
  2235. METADATA_PERMISSION_READ | METADATA_PERMISSION_WRITE
  2236. );
  2237. CError err2(mk2.QueryResult());
  2238. if (err2.Succeeded())
  2239. {
  2240. // Check if this node has an AppRoot Setting....
  2241. // if it does, then we have to rename that too.
  2242. // AppRoot : [IF] (STRING) "/LM/W3SVC/1/ROOT/MyVDir1"
  2243. BOOL fInherit = FALSE;
  2244. CString strAppRootOld;
  2245. err2 = mk2.QueryValue(MD_APP_ROOT, strAppRootOld, &fInherit);
  2246. if (err2.Succeeded())
  2247. {
  2248. // Write out new value
  2249. err2 = mk2.SetValue(MD_APP_ROOT, strNewPath);
  2250. }
  2251. mk2.Close();
  2252. }
  2253. }
  2254. return err;
  2255. }
  2256. //
  2257. // ISM Helpers
  2258. //
  2259. // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  2260. HRESULT
  2261. DetermineIfAdministrator(
  2262. IN CMetaInterface * pInterface,
  2263. IN LPCTSTR lpszMetabasePath,
  2264. OUT BOOL * pfAdministrator,
  2265. IN OUT DWORD * pdwMetabaseSystemChangeNumber
  2266. )
  2267. /*++
  2268. Routine Description:
  2269. Attempt to actually resolve whether or not the current user
  2270. has administrator or merely "operator" access. Until this method
  2271. is called by the derived class, the user is assumed to have
  2272. full administrator access, and may therefore get "access denied"
  2273. errors in inconvenient places.
  2274. The method to determine admin access is rather lame at the moment.
  2275. There's a dummy metabase property that only allows admins to write
  2276. to it, so we try to write to it to see if we're an admin.
  2277. Arguments:
  2278. CMetaInterface * pInterface : Metabase interface
  2279. LPCTSTR lpszMetabasePath : Metabase path
  2280. BOOL * pfAdministrator : Returns TRUE/FALSE for administrator
  2281. status
  2282. Return Value:
  2283. Error return code.
  2284. Notes:
  2285. This function used to be used on instance paths. Now uses simple metabase
  2286. paths.
  2287. --*/
  2288. {
  2289. ASSERT_WRITE_PTR(pfAdministrator);
  2290. ASSERT_PTR(pInterface);
  2291. ASSERT_PTR(pdwMetabaseSystemChangeNumber);
  2292. if (!pfAdministrator || !pInterface)
  2293. {
  2294. return E_POINTER;
  2295. }
  2296. *pfAdministrator = FALSE;
  2297. //
  2298. // Reuse existing interface we have lying around.
  2299. //
  2300. CMetaKey mk(pInterface);
  2301. CError err(mk.QueryResult());
  2302. if (err.Succeeded())
  2303. {
  2304. CString path(lpszMetabasePath);
  2305. while (FAILED(mk.DoesPathExist(path)))
  2306. {
  2307. // Goto parent
  2308. if (NULL == CMetabasePath::ConvertToParentPath(path))
  2309. {
  2310. break;
  2311. }
  2312. }
  2313. err = mk.Open(
  2314. METADATA_PERMISSION_READ | METADATA_PERMISSION_WRITE,
  2315. path
  2316. );
  2317. if (err.Succeeded())
  2318. {
  2319. //
  2320. // Write some nonsense
  2321. //
  2322. DWORD dwDummy = 0x1234;
  2323. err = mk.SetValue(MD_ISM_ACCESS_CHECK, dwDummy);
  2324. *pdwMetabaseSystemChangeNumber = *pdwMetabaseSystemChangeNumber + 1;
  2325. //
  2326. // And delete it again
  2327. //
  2328. if (err.Succeeded())
  2329. {
  2330. mk.DeleteValue(MD_ISM_ACCESS_CHECK);
  2331. *pdwMetabaseSystemChangeNumber = *pdwMetabaseSystemChangeNumber + 1;
  2332. }
  2333. mk.Close();
  2334. }
  2335. }
  2336. ASSERT(err.Succeeded() || err.Win32Error() == ERROR_ACCESS_DENIED);
  2337. *pfAdministrator = (err.Succeeded());
  2338. #ifdef _DEBUG
  2339. if (*pfAdministrator)
  2340. {
  2341. TRACEEOLID("You are a full admin.");
  2342. }
  2343. else
  2344. {
  2345. TRACEEOLID("You're just a lowly operator at best. Error code is " << err);
  2346. }
  2347. #endif // _DEBUG
  2348. if (err.Win32Error() == ERROR_ACCESS_DENIED)
  2349. {
  2350. //
  2351. // Expected result
  2352. //
  2353. err.Reset();
  2354. }
  2355. return err.Win32Error();
  2356. }
  2357. #if 0
  2358. //
  2359. // Dll Version Only
  2360. //
  2361. // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  2362. STDAPI
  2363. DllRegisterServer()
  2364. /*++
  2365. Routine Description:
  2366. DllRegisterServer - Adds entries to the system registry
  2367. Arguments:
  2368. None.
  2369. Return Value:
  2370. HRESULT
  2371. Notes:
  2372. This entry point doesn't do anything presently. It's here to function as a
  2373. placeholder, and because we don't want to fail being called by regsvr32.
  2374. --*/
  2375. {
  2376. return S_OK;
  2377. }
  2378. STDAPI
  2379. DllUnregisterServer()
  2380. /*++
  2381. Routine Description:
  2382. DllUnregisterServer - Removes entries from the system registry
  2383. Arguments:
  2384. None.
  2385. Return Value:
  2386. HRESULT
  2387. Notes:
  2388. See notes on DllRegisterServer above.
  2389. --*/
  2390. {
  2391. return S_OK;
  2392. }
  2393. static AFX_EXTENSION_MODULE extensionDLL = {NULL, NULL};
  2394. extern "C" int APIENTRY
  2395. DllMain(
  2396. IN HINSTANCE hInstance,
  2397. IN DWORD dwReason,
  2398. IN LPVOID lpReserved
  2399. )
  2400. /*++
  2401. Routine Description:
  2402. DLL Main entry point
  2403. Arguments:
  2404. HINSTANCE hInstance : Instance handle
  2405. DWORD dwReason : DLL_PROCESS_ATTACH, etc
  2406. LPVOID lpReserved : Reserved value
  2407. Return Value:
  2408. 1 for succesful initialisation, 0 for failed initialisation
  2409. --*/
  2410. {
  2411. switch (dwReason)
  2412. {
  2413. case DLL_PROCESS_ATTACH:
  2414. ASSERT(hInstance != NULL);
  2415. // hDLLInstance = hInstance;
  2416. if (!::AfxInitExtensionModule(extensionDLL, hInstance)
  2417. || !InitErrorFunctionality()
  2418. || !InitIntlSettings()
  2419. )
  2420. {
  2421. return 0;
  2422. }
  2423. #if defined(_DEBUG) || DBG
  2424. //
  2425. // Force tracing on.
  2426. //
  2427. afxTraceEnabled = TRUE;
  2428. #endif // _DEBUG
  2429. break;
  2430. case DLL_PROCESS_DETACH:
  2431. //
  2432. // termination
  2433. //
  2434. TerminateIntlSettings();
  2435. TerminateErrorFunctionality();
  2436. ::AfxTermExtensionModule(extensionDLL);
  2437. break;
  2438. }
  2439. //
  2440. // Succes loading the DLL
  2441. //
  2442. return 1;
  2443. }
  2444. #endif // IISUI_EXPORTS