Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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