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.

5009 lines
118 KiB

  1. /*++
  2. Copyright (c) 1994-2000 Microsoft Corporation
  3. Module Name :
  4. mdkeys.cpp
  5. Abstract:
  6. Metabase key wrapper class
  7. Author:
  8. Ronald Meijer (ronaldm)
  9. Sergei Antonov (sergeia)
  10. Project:
  11. Internet Services Manager
  12. Revision History:
  13. 2/17/2000 sergeia removed dependency on MFC
  14. --*/
  15. //
  16. // Include Files
  17. //
  18. #include "stdafx.h"
  19. #include "common.h"
  20. #include "inheritancedlg.h"
  21. #include "mdkeys.h"
  22. //
  23. // Constants
  24. //
  25. #define MB_TIMEOUT (15000) // Timeout in milliseconds
  26. #define MB_INIT_BUFF_SIZE ( 256) // Initial buffer size
  27. //
  28. // CComAuthInfo implementation
  29. //
  30. // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  31. /* static */
  32. BOOL
  33. CComAuthInfo::SplitUserNameAndDomain(
  34. IN OUT CString & strUserName,
  35. IN CString & strDomainName
  36. )
  37. /*++
  38. Routine Description:
  39. Split the user name and domain from the given
  40. username, which is in the format "domain\user".
  41. Return TRUE if the user name contained a domain
  42. FALSE if it did not
  43. Arguments:
  44. CString & strUserName : User name which may contain a domain name
  45. CString & strDomainName : Output domain name ("." if local)
  46. Return Value:
  47. TRUE if a domain is split off
  48. --*/
  49. {
  50. //
  51. // Assume local
  52. //
  53. strDomainName = _T(".");
  54. int nSlash = strUserName.Find(_T("\\"));
  55. if (nSlash >= 0)
  56. {
  57. strDomainName = strUserName.Left(nSlash);
  58. strUserName = strUserName.Mid(nSlash + 1);
  59. return TRUE;
  60. }
  61. return FALSE;
  62. }
  63. /* static */
  64. DWORD
  65. CComAuthInfo::VerifyUserPassword(
  66. IN LPCTSTR lpstrUserName,
  67. IN LPCTSTR lpstrPassword
  68. )
  69. /*++
  70. Routine Description:
  71. Verify the usernamer password combo checks out
  72. Arguments:
  73. LPCTSTR lpstrUserName : Domain/username combo
  74. LPCTSTR lpstrPassword : Password
  75. Return Value:
  76. ERROR_SUCCESS if the password checks out, an error code
  77. otherwise.
  78. --*/
  79. {
  80. CString strDomain;
  81. CString strUser(lpstrUserName);
  82. CString strPassword(lpstrPassword);
  83. SplitUserNameAndDomain(strUser, strDomain);
  84. //
  85. // In order to look up an account name, this process
  86. // must first be granted the privilege of doing so.
  87. //
  88. CError err;
  89. {
  90. HANDLE hToken;
  91. LUID AccountLookupValue;
  92. TOKEN_PRIVILEGES tkp;
  93. do
  94. {
  95. if (!::OpenProcessToken(GetCurrentProcess(),
  96. TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
  97. &hToken)
  98. )
  99. {
  100. err.GetLastWinError();
  101. break;
  102. }
  103. if (!::LookupPrivilegeValue(NULL, SE_TCB_NAME, &AccountLookupValue))
  104. {
  105. err.GetLastWinError();
  106. break;
  107. }
  108. tkp.PrivilegeCount = 1;
  109. tkp.Privileges[0].Luid = AccountLookupValue;
  110. tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
  111. ::AdjustTokenPrivileges(
  112. hToken,
  113. FALSE,
  114. &tkp,
  115. sizeof(TOKEN_PRIVILEGES),
  116. (PTOKEN_PRIVILEGES)NULL,
  117. (PDWORD)NULL
  118. );
  119. err.GetLastWinError();
  120. if (err.Failed())
  121. {
  122. break;
  123. }
  124. HANDLE hUser = NULL;
  125. if (::LogonUser(
  126. (LPTSTR)(LPCTSTR)strUser,
  127. (LPTSTR)(LPCTSTR)strDomain,
  128. (LPTSTR)(LPCTSTR)strPassword,
  129. LOGON32_LOGON_NETWORK,
  130. LOGON32_PROVIDER_DEFAULT,
  131. &hUser
  132. ))
  133. {
  134. //
  135. // Success!
  136. //
  137. CloseHandle(hUser);
  138. }
  139. else
  140. {
  141. err.GetLastWinError();
  142. }
  143. //
  144. // Remove the privilege
  145. //
  146. }
  147. while(FALSE);
  148. }
  149. HANDLE hUser = NULL;
  150. if (::LogonUser(
  151. (LPTSTR)(LPCTSTR)strUser,
  152. (LPTSTR)(LPCTSTR)strDomain,
  153. (LPTSTR)(LPCTSTR)strPassword,
  154. LOGON32_LOGON_NETWORK,
  155. LOGON32_PROVIDER_DEFAULT,
  156. &hUser))
  157. {
  158. //
  159. // Success!
  160. //
  161. CloseHandle(hUser);
  162. }
  163. else
  164. {
  165. err.GetLastWinError();
  166. }
  167. return err;
  168. }
  169. CComAuthInfo::CComAuthInfo(
  170. IN LPCOLESTR lpszServerName OPTIONAL,
  171. IN LPCOLESTR lpszUserName OPTIONAL,
  172. IN LPCOLESTR lpszPassword OPTIONAL
  173. )
  174. /*++
  175. Routine Description:
  176. Construct CIIServer object
  177. Argument:
  178. LPCOLESTR lpszServerName : Server name or NULL for local computer
  179. LPCOLESTR lpszUserName : User name of blank for no impersonation
  180. LPCOLESTR lpszPassword : Password (might be blank or NULL)
  181. Return Value:
  182. N/A
  183. --*/
  184. : m_bstrServerName(),
  185. m_bstrUserName(lpszUserName),
  186. m_bstrPassword(lpszPassword),
  187. m_fLocal(FALSE)
  188. {
  189. SetComputerName(lpszServerName);
  190. }
  191. CComAuthInfo::CComAuthInfo(
  192. IN CComAuthInfo & auth
  193. )
  194. /*++
  195. Routine Description:
  196. Copy constructor
  197. Arguments:
  198. CComAuthInfo & auth : Source object to copy from
  199. Return Value:
  200. N/A
  201. --*/
  202. : m_bstrServerName(auth.m_bstrServerName),
  203. m_bstrUserName(auth.m_bstrUserName),
  204. m_bstrPassword(auth.m_bstrPassword),
  205. m_fLocal(auth.m_fLocal)
  206. {
  207. }
  208. CComAuthInfo::CComAuthInfo(
  209. IN CComAuthInfo * pAuthInfo OPTIONAL
  210. )
  211. /*++
  212. Routine Description:
  213. Copy constructor
  214. Arguments:
  215. CComAuthInfo * pAuthInfo : Source object to copy from (or NULL)
  216. Return Value:
  217. N/A
  218. --*/
  219. : m_bstrServerName(),
  220. m_bstrUserName(),
  221. m_bstrPassword(),
  222. m_fLocal(FALSE)
  223. {
  224. if (pAuthInfo)
  225. {
  226. //
  227. // Full authentication information available
  228. //
  229. m_bstrUserName = pAuthInfo->m_bstrUserName;
  230. m_bstrPassword = pAuthInfo->m_bstrPassword;
  231. m_bstrServerName = pAuthInfo->m_bstrServerName;
  232. m_fLocal = pAuthInfo->m_fLocal;
  233. }
  234. else
  235. {
  236. //
  237. // Local computer w/o impersonation
  238. //
  239. SetComputerName(NULL);
  240. }
  241. }
  242. CComAuthInfo &
  243. CComAuthInfo::operator =(
  244. IN CComAuthInfo & auth
  245. )
  246. /*++
  247. Routine Description:
  248. Assignment operator
  249. Arguments:
  250. CComAuthInfo & auth : Source object to copy from
  251. Return Value:
  252. Reference to current object
  253. --*/
  254. {
  255. m_bstrServerName = auth.m_bstrServerName;
  256. m_bstrUserName = auth.m_bstrUserName;
  257. m_bstrPassword = auth.m_bstrPassword;
  258. m_fLocal = auth.m_fLocal;
  259. return *this;
  260. }
  261. CComAuthInfo &
  262. CComAuthInfo::operator =(
  263. IN CComAuthInfo * pAuthInfo OPTIONAL
  264. )
  265. /*++
  266. Routine Description:
  267. Assignment operator
  268. Arguments:
  269. CComAuthInfo * pAuthInfo : Source object to copy from (or NULL)
  270. Return Value:
  271. Reference to current object
  272. --*/
  273. {
  274. if (pAuthInfo)
  275. {
  276. m_bstrUserName = pAuthInfo->m_bstrUserName;
  277. m_bstrPassword = pAuthInfo->m_bstrPassword;
  278. SetComputerName(pAuthInfo->m_bstrServerName);
  279. }
  280. else
  281. {
  282. //
  283. // Local computer w/o impersonation
  284. //
  285. m_bstrUserName.Empty();
  286. m_bstrPassword.Empty();
  287. SetComputerName(NULL);
  288. }
  289. return *this;
  290. }
  291. CComAuthInfo &
  292. CComAuthInfo::operator =(
  293. IN LPCTSTR lpszServerName
  294. )
  295. /*++
  296. Routine Description:
  297. Assignment operator. Assign computer name w/o impersonation
  298. Arguments:
  299. LPCTSTR lpszServerName : Source server name
  300. Return Value:
  301. Reference to current object
  302. --*/
  303. {
  304. RemoveImpersonation();
  305. SetComputerName(lpszServerName);
  306. return *this;
  307. }
  308. void
  309. CComAuthInfo::SetComputerName(
  310. IN LPCOLESTR lpszServerName OPTIONAL
  311. )
  312. /*++
  313. Routine Description:
  314. Store the computer name. Determine if its local.
  315. Arguments:
  316. LPCOLESTR lpszServername : Server name. NULL indicates the local computer
  317. Return Value:
  318. None
  319. --*/
  320. {
  321. if (lpszServerName && *lpszServerName)
  322. {
  323. //
  324. // Specific computer name specified
  325. //
  326. m_bstrServerName = lpszServerName;
  327. m_fLocal = ::IsServerLocal(lpszServerName);
  328. }
  329. else
  330. {
  331. //
  332. // Use local computer name
  333. //
  334. // CODEWORK: Cache static version of computername maybe?
  335. //
  336. TCHAR szLocalServer[MAX_PATH + 1];
  337. DWORD dwSize = MAX_PATH;
  338. VERIFY(::GetComputerName(szLocalServer, &dwSize));
  339. m_bstrServerName = szLocalServer;
  340. m_fLocal = TRUE;
  341. }
  342. }
  343. void
  344. CComAuthInfo::SetImpersonation(
  345. IN LPCOLESTR lpszUser,
  346. IN LPCOLESTR lpszPassword
  347. )
  348. /*++
  349. Routine Description:
  350. Set impersonation parameters
  351. Arguments:
  352. LPCOLESTR lpszUser : User name
  353. LPCOLESTR lpszPassword : Password
  354. Return Value:
  355. None
  356. --*/
  357. {
  358. m_bstrUserName = lpszUser;
  359. StorePassword(lpszPassword);
  360. }
  361. void
  362. CComAuthInfo::RemoveImpersonation()
  363. /*++
  364. Routine Description:
  365. Remove impersonation parameters
  366. Arguments:
  367. None
  368. Return Value:
  369. None
  370. --*/
  371. {
  372. m_bstrUserName.Empty();
  373. m_bstrPassword.Empty();
  374. }
  375. COSERVERINFO *
  376. CComAuthInfo::CreateServerInfoStruct() const
  377. {
  378. return (CComAuthInfo::CreateServerInfoStruct(RPC_C_AUTHN_LEVEL_DEFAULT));
  379. }
  380. COSERVERINFO *
  381. CComAuthInfo::CreateServerInfoStruct(DWORD dwAuthnLevel) const
  382. /*++
  383. Routine Description:
  384. Create the server info structure. Might return NULL for the no frills case.
  385. Arguments:
  386. NULL
  387. Return Value:
  388. A COSERVERINFO structure, or NULL if the computer is local, and no
  389. impersonation is required.
  390. Notes:
  391. Caller must call FreeServerInfoStruct() to prevent memory leaks
  392. --*/
  393. {
  394. //
  395. // Be smart about the server name; optimize for local
  396. // computer name.
  397. //
  398. if (m_fLocal && !UsesImpersonation())
  399. {
  400. //
  401. // Special, no-frills case.
  402. //
  403. return NULL;
  404. }
  405. //
  406. // Create the COM server info for CoCreateInstanceEx
  407. //
  408. COSERVERINFO * pcsiName = NULL;
  409. do
  410. {
  411. pcsiName = new COSERVERINFO;
  412. if (!pcsiName)
  413. {
  414. break;
  415. }
  416. ZeroMemory(pcsiName, sizeof(COSERVERINFO));
  417. pcsiName->pwszName = m_bstrServerName;
  418. //
  419. // Set impersonation
  420. //
  421. if (UsesImpersonation())
  422. {
  423. COAUTHINFO * pAuthInfo = new COAUTHINFO;
  424. if (!pAuthInfo)
  425. {
  426. break;
  427. }
  428. ZeroMemory(pAuthInfo, sizeof(COAUTHINFO));
  429. COAUTHIDENTITY * pAuthIdentityData = new COAUTHIDENTITY;
  430. if (!pAuthIdentityData)
  431. {
  432. break;
  433. }
  434. ZeroMemory(pAuthIdentityData, sizeof(COAUTHIDENTITY));
  435. CString strUserName(m_bstrUserName);
  436. CString strPassword(m_bstrPassword);
  437. CString strDomain;
  438. //
  439. // Break up domain\username combo
  440. //
  441. SplitUserNameAndDomain(strUserName, strDomain);
  442. pAuthIdentityData->UserLength = strUserName.GetLength();
  443. if (pAuthIdentityData->UserLength != 0)
  444. {
  445. pAuthIdentityData->User = StrDup(strUserName);
  446. }
  447. pAuthIdentityData->DomainLength = strDomain.GetLength();
  448. if (pAuthIdentityData->DomainLength != 0)
  449. {
  450. pAuthIdentityData->Domain = StrDup(strDomain);
  451. }
  452. pAuthIdentityData->PasswordLength = strPassword.GetLength();
  453. if (pAuthIdentityData->PasswordLength)
  454. {
  455. pAuthIdentityData->Password = StrDup(strPassword);
  456. }
  457. // RPC_C_AUTHN_LEVEL_DEFAULT 0
  458. // RPC_C_AUTHN_LEVEL_NONE 1
  459. // RPC_C_AUTHN_LEVEL_CONNECT 2
  460. // RPC_C_AUTHN_LEVEL_CALL 3
  461. // RPC_C_AUTHN_LEVEL_PKT 4
  462. // RPC_C_AUTHN_LEVEL_PKT_INTEGRITY 5
  463. // RPC_C_AUTHN_LEVEL_PKT_PRIVACY 6
  464. // you can only specify stuff stronger than RPC_C_AUTHN_LEVEL_CONNECT
  465. if (RPC_C_AUTHN_LEVEL_DEFAULT != dwAuthnLevel)
  466. {
  467. if (dwAuthnLevel >= RPC_C_AUTHN_LEVEL_CONNECT && dwAuthnLevel <= RPC_C_AUTHN_LEVEL_PKT_PRIVACY)
  468. {
  469. pAuthInfo->dwAuthnLevel = dwAuthnLevel;
  470. }
  471. else
  472. {
  473. pAuthInfo->dwAuthnLevel = RPC_C_AUTHN_LEVEL_CONNECT;
  474. }
  475. }
  476. else
  477. {
  478. pAuthInfo->dwAuthnLevel = RPC_C_AUTHN_LEVEL_DEFAULT;
  479. }
  480. pAuthIdentityData->Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
  481. pAuthInfo->dwImpersonationLevel = RPC_C_IMP_LEVEL_IMPERSONATE;
  482. pAuthInfo->dwAuthnSvc = RPC_C_AUTHN_WINNT;
  483. pAuthInfo->dwAuthzSvc = RPC_C_AUTHZ_NONE;
  484. pAuthInfo->pwszServerPrincName = NULL;
  485. pAuthInfo->dwCapabilities = EOAC_NONE;
  486. pAuthInfo->pAuthIdentityData = pAuthIdentityData;
  487. pcsiName->pAuthInfo = pAuthInfo;
  488. }
  489. }
  490. while(FALSE);
  491. return pcsiName;
  492. }
  493. void
  494. CComAuthInfo::FreeServerInfoStruct(
  495. IN COSERVERINFO * pServerInfo
  496. ) const
  497. /*++
  498. Routine Description:
  499. As mentioned above -- free the server info structure
  500. Arguments:
  501. COSERVERINFO * pServerInfo : Server info structure
  502. Return Value:
  503. None
  504. --*/
  505. {
  506. if (pServerInfo)
  507. {
  508. if (pServerInfo->pAuthInfo)
  509. {
  510. if (pServerInfo->pAuthInfo->pAuthIdentityData)
  511. {
  512. if (pServerInfo->pAuthInfo->pAuthIdentityData)
  513. {
  514. LocalFree(pServerInfo->pAuthInfo->pAuthIdentityData->User);
  515. LocalFree(pServerInfo->pAuthInfo->pAuthIdentityData->Domain);
  516. LocalFree(pServerInfo->pAuthInfo->pAuthIdentityData->Password);
  517. delete pServerInfo->pAuthInfo->pAuthIdentityData;
  518. }
  519. }
  520. delete pServerInfo->pAuthInfo;
  521. }
  522. delete pServerInfo;
  523. }
  524. }
  525. HRESULT
  526. CComAuthInfo::ApplyProxyBlanket(
  527. IN OUT IUnknown * pInterface
  528. )
  529. /*++
  530. Routine Description:
  531. Set security information on the interface. The user name is of the form
  532. domain\username.
  533. Arguments:
  534. IUnknown * pInterface : Interface
  535. Return Value:
  536. HRESULT
  537. --*/
  538. {
  539. HRESULT hr = S_OK;
  540. COSERVERINFO * pcsiName = CreateServerInfoStruct();
  541. //
  542. // This method should only be called if we're using impersonation.
  543. // so the pcsiName returned should never be NULL.
  544. //
  545. ATLASSERT(pcsiName && pcsiName->pAuthInfo);
  546. DWORD dwAuthSvc, dwAuthzSvc, dwAuthnLevel, dwImplLevel, dwCaps;
  547. OLECHAR * pServerPrincName;
  548. RPC_AUTH_IDENTITY_HANDLE pAuthInfo;
  549. hr = ::CoQueryProxyBlanket(
  550. pInterface,
  551. &dwAuthSvc,
  552. &dwAuthzSvc,
  553. &pServerPrincName,
  554. &dwAuthnLevel,
  555. &dwImplLevel,
  556. &pAuthInfo,
  557. &dwCaps);
  558. if (pcsiName && pcsiName->pAuthInfo)
  559. {
  560. hr = ::CoSetProxyBlanket(
  561. pInterface,
  562. pcsiName->pAuthInfo->dwAuthnSvc,
  563. pcsiName->pAuthInfo->dwAuthzSvc,
  564. pcsiName->pAuthInfo->pwszServerPrincName,
  565. pcsiName->pAuthInfo->dwAuthnLevel,
  566. pcsiName->pAuthInfo->dwImpersonationLevel,
  567. pcsiName->pAuthInfo->pAuthIdentityData,
  568. pcsiName->pAuthInfo->dwCapabilities
  569. );
  570. FreeServerInfoStruct(pcsiName);
  571. }
  572. return hr;
  573. }
  574. HRESULT
  575. CComAuthInfo::ApplyProxyBlanket(
  576. IN OUT IUnknown * pInterface,
  577. IN DWORD dwAuthnLevelInput
  578. )
  579. /*++
  580. Routine Description:
  581. Set security information on the interface. The user name is of the form
  582. domain\username.
  583. Arguments:
  584. IUnknown * pInterface : Interface
  585. Return Value:
  586. HRESULT
  587. --*/
  588. {
  589. HRESULT hr = S_OK;
  590. COSERVERINFO * pcsiName = CreateServerInfoStruct(dwAuthnLevelInput);
  591. //
  592. // This method should only be called if we're using impersonation.
  593. // so the pcsiName returned should never be NULL.
  594. //
  595. ATLASSERT(pcsiName && pcsiName->pAuthInfo);
  596. DWORD dwAuthSvc, dwAuthzSvc, dwAuthnLevel, dwImplLevel, dwCaps;
  597. OLECHAR * pServerPrincName;
  598. RPC_AUTH_IDENTITY_HANDLE pAuthInfo;
  599. hr = ::CoQueryProxyBlanket(
  600. pInterface,
  601. &dwAuthSvc,
  602. &dwAuthzSvc,
  603. &pServerPrincName,
  604. &dwAuthnLevel,
  605. &dwImplLevel,
  606. &pAuthInfo,
  607. &dwCaps);
  608. if (pcsiName && pcsiName->pAuthInfo)
  609. {
  610. hr = ::CoSetProxyBlanket(
  611. pInterface,
  612. pcsiName->pAuthInfo->dwAuthnSvc,
  613. pcsiName->pAuthInfo->dwAuthzSvc,
  614. pcsiName->pAuthInfo->pwszServerPrincName,
  615. pcsiName->pAuthInfo->dwAuthnLevel,
  616. pcsiName->pAuthInfo->dwImpersonationLevel,
  617. pcsiName->pAuthInfo->pAuthIdentityData,
  618. pcsiName->pAuthInfo->dwCapabilities
  619. );
  620. FreeServerInfoStruct(pcsiName);
  621. }
  622. return hr;
  623. }
  624. //
  625. // CMetabasePath implemention
  626. //
  627. // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  628. const LPCTSTR CMetabasePath::_cszMachine = SZ_MBN_MACHINE;
  629. const LPCTSTR CMetabasePath::_cszRoot = SZ_MBN_ROOT;
  630. const LPCTSTR CMetabasePath::_cszSep = SZ_MBN_SEP_STR;
  631. const TCHAR CMetabasePath::_chSep = SZ_MBN_SEP_CHAR;
  632. const CString CMetabasePath::_anySep = SZ_MBN_ANYSEP_STR;
  633. /*static*/
  634. BOOL
  635. CMetabasePath::IsSeparator(TCHAR c)
  636. {
  637. return _anySep.find(c) != CString::npos;
  638. }
  639. /* static */
  640. LPCTSTR
  641. CMetabasePath::ConvertToParentPath(
  642. OUT IN CString & strMetaPath
  643. )
  644. /*++
  645. Routine Description:
  646. Given the path, convert it to the parent path
  647. e.g. "foo/bar/etc" returns "foo/bar"
  648. Arguments:
  649. CString & strMetaPath : Path to be converted
  650. Return value:
  651. Pointer to the converted path, or NULL in case of error
  652. --*/
  653. {
  654. // TRACE(_T("Getting parent path of %s\n"), strMetaPath);
  655. CString::size_type pos, pos_head;
  656. if ((pos = strMetaPath.find_last_of(SZ_MBN_ANYSEP_STR)) == strMetaPath.length() - 1)
  657. {
  658. strMetaPath.erase(pos);
  659. }
  660. pos = strMetaPath.find_last_of(SZ_MBN_ANYSEP_STR);
  661. if (pos == CString::npos)
  662. return strMetaPath;
  663. pos_head = strMetaPath.find_first_of(SZ_MBN_ANYSEP_STR);
  664. if (pos_head != pos)
  665. {
  666. strMetaPath.erase(pos);
  667. }
  668. // TRACE(_T("Parent path should be %s\n"), strMetaPath);
  669. return strMetaPath;
  670. }
  671. LPCTSTR
  672. CMetabasePath::ConvertToParentPath(
  673. CMetabasePath& path
  674. )
  675. {
  676. return CMetabasePath::ConvertToParentPath(path.m_strMetaPath);
  677. }
  678. /* static */
  679. LPCTSTR
  680. CMetabasePath::TruncatePath(
  681. IN int nLevel,
  682. IN LPCTSTR lpszMDPath,
  683. OUT CString & strNewPath,
  684. OUT CString * pstrRemainder OPTIONAL
  685. )
  686. /*++
  687. Routine Description:
  688. Truncate the given metabase path at the given level, that is,
  689. the nLevel'th separator in the path, starting at 0, where 0 will
  690. always give lpszPath back whether it started with a separator or not.
  691. Examples:
  692. "/lm/w3svc/1/foo" at level 2 returns "/lm/w3svc" as does
  693. "lm/w3svc/1/foo".
  694. Arguments:
  695. int nLevel 0-based separator count to truncate at.
  696. LPTSTR lpszMDPath Fully-qualified metabase path
  697. CString & strNewPath Returns truncated path
  698. CString * pstrRemainder Optionally returns the remainder past
  699. the nLevel'th separator.
  700. Return Value:
  701. The truncated path at the level requested. See examples above. *pstrRemainder
  702. returns the remainder of the path. If the path does not contain nLevel
  703. worth of separators, the entire path is returned, and the remainder will be
  704. blank.
  705. --*/
  706. {
  707. // ASSERT_PTR(lpszMDPath);
  708. ATLASSERT(nLevel >= 0);
  709. if (!lpszMDPath || nLevel < 0)
  710. {
  711. // TRACE(_T("TruncatePath: Invalid parameter\n"));
  712. return NULL;
  713. }
  714. // TRACE(_T("Source Path: %s\n"), lpszMDPath);
  715. //
  716. // Skip the first sep whether it exists or not
  717. //
  718. LPCTSTR lp = IsSeparator(*lpszMDPath) ? lpszMDPath + 1 : lpszMDPath;
  719. LPCTSTR lpRem = NULL;
  720. int cSeparators = 0;
  721. if (nLevel)
  722. {
  723. //
  724. // Advance to the requested separator level
  725. //
  726. while (*lp)
  727. {
  728. if (IsSeparator(*lp))
  729. {
  730. if (++cSeparators == nLevel)
  731. {
  732. break;
  733. }
  734. }
  735. ++lp;
  736. }
  737. if (!*lp)
  738. {
  739. //
  740. // End of path is considered a separator
  741. //
  742. ++cSeparators;
  743. }
  744. ATLASSERT(cSeparators <= nLevel);
  745. if (cSeparators == nLevel)
  746. {
  747. //
  748. // Break up the strings
  749. //
  750. strNewPath = lpszMDPath;
  751. strNewPath.erase(lp - lpszMDPath);
  752. // TRACE(_T("Path truncated at level %d : %s\n"), nLevel, strNewPath);
  753. if (*lp)
  754. {
  755. lpRem = ++lp;
  756. // TRACE(_T("Remainder: %s\n"), lpRem);
  757. }
  758. }
  759. }
  760. //
  761. // Return remainder
  762. //
  763. if (pstrRemainder && lpRem)
  764. {
  765. // ASSERT_WRITE_PTR(pstrRemainder);
  766. *pstrRemainder = lpRem;
  767. }
  768. return strNewPath;
  769. }
  770. /* static */
  771. DWORD
  772. CMetabasePath::GetInstanceNumber(
  773. IN LPCTSTR lpszMDPath
  774. )
  775. /*++
  776. Routine Description:
  777. Get the number of the instance referred to in the given metabase
  778. path.
  779. Examples: "lm/w3svc/1/foo/bar" will return 1
  780. "lm/w3svc/" will return 0 (master instance)
  781. "lm/bogus/path/" will return 0xffffffff (error)
  782. Arguments:
  783. LPCTSTR lpszMDPath : A metabase path.
  784. Return Value:
  785. Instance number (0 indicates master instance)
  786. or 0xffffffff if the path is in error.
  787. --*/
  788. {
  789. // TRACE(_T("Determining instance number of %s\n"), lpszMDPath);
  790. DWORD dwInstance = 0xffffffff;
  791. CString strService, strInst;
  792. if (GetServicePath(lpszMDPath, strService, &strInst))
  793. {
  794. if (strInst.IsEmpty())
  795. {
  796. dwInstance = MASTER_INSTANCE;
  797. }
  798. else
  799. {
  800. if (_istdigit(strInst.GetAt(0)))
  801. {
  802. dwInstance = _ttol(strInst);
  803. }
  804. }
  805. }
  806. return dwInstance;
  807. }
  808. /* static */
  809. LPCTSTR
  810. CMetabasePath::GetLastNodeName(
  811. IN LPCTSTR lpszMDPath,
  812. OUT CString & strNodeName
  813. )
  814. /*++
  815. Routine Description:
  816. Get the last nodename off the metabase path
  817. Example:
  818. "/lm/foo/bar/" returns "bar"
  819. Arguments:
  820. LPCTSTR lpszMDPath : Metabase path
  821. Return Value:
  822. Pointer to the node name or NULL in case of a malformed path.
  823. --*/
  824. {
  825. // ASSERT_PTR(lpszMDPath);
  826. if (!lpszMDPath || !*lpszMDPath)
  827. {
  828. return NULL;
  829. }
  830. // TRACE(_T("Getting last node name from %s\n"), lpszMDPath);
  831. LPCTSTR lp;
  832. LPCTSTR lpTail;
  833. lp = lpTail = lpszMDPath + lstrlen(lpszMDPath) - 1;
  834. //
  835. // Skip trailing separator
  836. //
  837. if (IsSeparator(*lp))
  838. {
  839. --lpTail;
  840. --lp;
  841. }
  842. strNodeName.Empty();
  843. while (*lp && !IsSeparator(*lp))
  844. {
  845. strNodeName += *(lp--);
  846. }
  847. strNodeName.MakeReverse();
  848. // TRACE(_T("Node is %s\n"), strNodeName);
  849. return strNodeName;
  850. }
  851. /* static */
  852. void
  853. CMetabasePath::SplitMetaPathAtInstance(
  854. IN LPCTSTR lpszMDPath,
  855. OUT CString & strParent,
  856. OUT CString & strAlias
  857. )
  858. /*++
  859. Routine Description:
  860. Split the given path into parent metabase root and alias, with the root
  861. being the instance path, and the alias everything following the
  862. instance.
  863. Arguments:
  864. LPCTSTR lpszMDPath : Input path
  865. CString & strParent : Outputs the parent path
  866. CString & strAlias : Outputs the alias name
  867. Return Value:
  868. None.
  869. --*/
  870. {
  871. // ASSERT_PTR(lpszMDPath);
  872. // TRACE(_T("Source Path %s\n"), lpszMDPath);
  873. strParent = lpszMDPath;
  874. strAlias.Empty();
  875. LPTSTR lp = (LPTSTR)lpszMDPath;
  876. if (lp == NULL)
  877. {
  878. return;
  879. }
  880. int cSeparators = 0;
  881. int iChar = 0;
  882. //
  883. // Looking for "LM/sss/ddd/" <-- 3d slash:
  884. //
  885. while (*lp && cSeparators < 2)
  886. {
  887. if (IsSeparator(*lp))
  888. {
  889. ++cSeparators;
  890. }
  891. ++iChar;
  892. }
  893. if (!*lp)
  894. {
  895. //
  896. // Bogus format
  897. //
  898. ASSERT_MSG("Bogus Format");
  899. return;
  900. }
  901. if (_istdigit(*lp))
  902. {
  903. //
  904. // Not at the master instance, skip one more.
  905. //
  906. while (*lp)
  907. {
  908. ++iChar;
  909. if (IsSeparator(*lp++))
  910. {
  911. break;
  912. }
  913. }
  914. if (!*lp)
  915. {
  916. //
  917. // Bogus format
  918. //
  919. ASSERT_MSG("Bogus Format");
  920. return;
  921. }
  922. }
  923. strAlias = strParent.Mid(iChar);
  924. strParent.erase(iChar);
  925. // TRACE(_T("Broken up into %s\n"), strParent);
  926. // TRACE(_T(" and %s\n"), strAlias);
  927. }
  928. /* static */
  929. BOOL
  930. CMetabasePath::IsHomeDirectoryPath(
  931. IN LPCTSTR lpszMetaPath
  932. )
  933. /*++
  934. Routine Description:
  935. Determine if the path given describes a root directory
  936. Arguments:
  937. LPCTSTR lpszMetaPath : Metabase path
  938. Return Value:
  939. TRUE if the path describes a root directory,
  940. FALSE if it does not
  941. --*/
  942. {
  943. // ASSERT_READ_PTR(lpszMetaPath);
  944. LPTSTR lpNode = lpszMetaPath ? StrPBrk(lpszMetaPath, _anySep) : NULL;
  945. if (lpNode)
  946. {
  947. return _tcsicmp(++lpNode, _cszRoot) == 0;
  948. }
  949. return FALSE;
  950. }
  951. /* static */
  952. BOOL
  953. CMetabasePath::IsMasterInstance(
  954. IN LPCTSTR lpszMDPath
  955. )
  956. /*++
  957. Routine Description:
  958. Determine if the given metabase path points to the master instance
  959. (site). This is essentially the service path.
  960. Arguments:
  961. LPCTSTR lpszMDPath : Metabase path.
  962. Return Value:
  963. TRUE if the path is the master instance,
  964. FALSE otherwise.
  965. --*/
  966. {
  967. // ASSERT_READ_PTR(lpszMDPath);
  968. if (!lpszMDPath || !*lpszMDPath)
  969. {
  970. return FALSE;
  971. }
  972. // TRACE(_T("Checking path %s\n"), lpszMDPath);
  973. CString strService;
  974. CString strRemainder;
  975. LPCTSTR lpPath = TruncatePath(2, lpszMDPath, strService, &strRemainder);
  976. return lpPath && !strService.IsEmpty() && strRemainder.IsEmpty();
  977. }
  978. /* static */
  979. LPCTSTR
  980. CMetabasePath::GetServiceInfoPath(
  981. IN LPCTSTR lpszMDPath,
  982. OUT CString & strInfoPath,
  983. IN LPCTSTR lpszDefService OPTIONAL
  984. )
  985. /*++
  986. Routine Description:
  987. Generate the appropriate metabase service info path for the given
  988. metabase path.
  989. For example:
  990. "lm/w3svc/1/foo/bar" Generates "lm/w3svc/info"
  991. Arguments:
  992. LPCTSTR lpszMDPath : Input metabase path
  993. CString & strInfoPath : Returns the info path
  994. LPCTSTR lpszDefService : Optionally specifies the default service to
  995. use (e.g "w3svc") if no service could be found
  996. in the path.
  997. Return Value:
  998. The info metabase path or NULL if one could not be generated.
  999. --*/
  1000. {
  1001. //
  1002. // Capability info stored off the service path ("lm/w3svc").
  1003. //
  1004. CString strService;
  1005. CString strRem;
  1006. //
  1007. // Strip off everything past the service
  1008. //
  1009. if (!TruncatePath(2, lpszMDPath, strService, &strRem)
  1010. || strService.IsEmpty())
  1011. {
  1012. if (!lpszDefService)
  1013. {
  1014. // TRACEEOLID("Unable to generate info path");
  1015. return NULL;
  1016. }
  1017. TRACEEOLID("Using default service for info path");
  1018. //
  1019. // Machine path (no service). Use web as default service to
  1020. // look for capability and version info.
  1021. //
  1022. strService = CMetabasePath(TRUE, lpszDefService);
  1023. }
  1024. strInfoPath = CMetabasePath(FALSE, strService, SZ_MBN_INFO);
  1025. // TRACE("Using %s to look for capability info\n", strInfoPath);
  1026. return strInfoPath;
  1027. }
  1028. /* static */
  1029. LPCTSTR
  1030. CMetabasePath::CleanMetaPath(
  1031. IN OUT CString & strMetaRoot
  1032. )
  1033. /*++
  1034. Routine Description:
  1035. Clean up the metabase path to one valid for internal consumption.
  1036. This removes the beginning and trailing slashes off the path.
  1037. Arguments:
  1038. CString & strMetaRoot : Metabase path to be cleaned up.
  1039. Return Value:
  1040. Pointer to the metabase path
  1041. --*/
  1042. {
  1043. if (!strMetaRoot.IsEmpty())
  1044. {
  1045. int hd = strMetaRoot.find_first_not_of(SZ_MBN_ANYSEP_STR);
  1046. int tl = strMetaRoot.find_last_not_of(SZ_MBN_ANYSEP_STR);
  1047. if (hd == CString::npos && tl == CString::npos)
  1048. {
  1049. // path contains only separators
  1050. strMetaRoot.erase();
  1051. return strMetaRoot;
  1052. }
  1053. else if (hd != CString::npos)
  1054. {
  1055. if (tl != CString::npos)
  1056. tl++;
  1057. strMetaRoot = strMetaRoot.substr(hd, tl - hd);
  1058. }
  1059. #if 0
  1060. while (strMetaRoot.GetLength() > 0
  1061. && IsSeparator(strMetaRoot[strMetaRoot.GetLength() - 1]))
  1062. {
  1063. strMetaRoot.erase(strMetaRoot.GetLength() - 1);
  1064. }
  1065. while (strMetaRoot.GetLength() > 0
  1066. && IsSeparator(strMetaRoot[0]))
  1067. {
  1068. strMetaRoot = strMetaRoot.Right(strMetaRoot.GetLength() - 1);
  1069. }
  1070. #endif
  1071. // looks like IISAdmin works only with separators "/"
  1072. for (int i = 0; i < strMetaRoot.GetLength(); i++)
  1073. {
  1074. if (IsSeparator(strMetaRoot[i]))
  1075. strMetaRoot.SetAt(i, _chSep);
  1076. }
  1077. }
  1078. return strMetaRoot;
  1079. }
  1080. /* static */
  1081. LPCTSTR
  1082. CMetabasePath::CleanMetaPath(
  1083. IN OUT CMetabasePath & path
  1084. )
  1085. {
  1086. return CleanMetaPath(path.m_strMetaPath);
  1087. }
  1088. CMetabasePath::CMetabasePath(
  1089. IN BOOL fAddBasePath,
  1090. IN LPCTSTR lpszMDPath,
  1091. IN LPCTSTR lpszMDPath2 OPTIONAL,
  1092. IN LPCTSTR lpszMDPath3 OPTIONAL,
  1093. IN LPCTSTR lpszMDPath4 OPTIONAL
  1094. )
  1095. /*++
  1096. Routine Description:
  1097. Constructor.
  1098. Arguments:
  1099. BOOL fAddBasePath : TRUE to prepend base path ("LM")
  1100. FALSE if the path is complete
  1101. LPCTSTR lpszMDPath : Metabase path
  1102. LPCTSTR lpszMDPath2 : Optional child path
  1103. LPCTSTR lpszMDPath3 : Optional child path
  1104. LPCTSTR lpszMDPath4 : Optional child path
  1105. Return Value:
  1106. N/A
  1107. --*/
  1108. : m_strMetaPath()
  1109. {
  1110. // This will fail for NULL pointer
  1111. // ASSERT_READ_PTR(lpszMDPath);
  1112. if (fAddBasePath)
  1113. {
  1114. m_strMetaPath = _cszMachine;
  1115. AppendPath(lpszMDPath);
  1116. }
  1117. else
  1118. {
  1119. m_strMetaPath = lpszMDPath;
  1120. }
  1121. //
  1122. // Add optional path components
  1123. //
  1124. AppendPath(lpszMDPath2);
  1125. AppendPath(lpszMDPath3);
  1126. AppendPath(lpszMDPath4);
  1127. }
  1128. CMetabasePath::CMetabasePath(
  1129. IN LPCTSTR lpszSvc, OPTIONAL
  1130. IN DWORD dwInstance, OPTIONAL
  1131. IN LPCTSTR lpszParentPath, OPTIONAL
  1132. IN LPCTSTR lpszAlias OPTIONAL
  1133. )
  1134. /*++
  1135. Routine Description:
  1136. Constructor. Construct with path components.
  1137. Arguments:
  1138. LPCTSTR lpszSvc : Service (may be NULL or "")
  1139. DWORD dwInstance : Instance number (may be 0 for master)
  1140. LPCTSTR lpszParentPath : Parent path (may be NULL or "")
  1141. LPCTSTR lpszAlias : Alias (may be NULL or "")
  1142. Return Value:
  1143. N/A
  1144. --*/
  1145. : m_strMetaPath()
  1146. {
  1147. BuildMetaPath(lpszSvc, dwInstance, lpszParentPath, lpszAlias);
  1148. }
  1149. void
  1150. CMetabasePath::AppendPath(
  1151. IN LPCTSTR lpszPath
  1152. )
  1153. /*++
  1154. Routine Description:
  1155. Append path to current metabase path
  1156. Arguments:
  1157. LPCTSTR lpszPath : Metabase path
  1158. Return Value:
  1159. None
  1160. --*/
  1161. {
  1162. if (lpszPath && *lpszPath)
  1163. {
  1164. m_strMetaPath += _cszSep;
  1165. m_strMetaPath += lpszPath;
  1166. }
  1167. }
  1168. void
  1169. CMetabasePath::AppendPath(
  1170. IN DWORD dwInstance
  1171. )
  1172. /*++
  1173. Routine Description:
  1174. Append path to current metabase path
  1175. Arguments:
  1176. DWORD dwInstance : Instance path
  1177. Return Value:
  1178. None
  1179. --*/
  1180. {
  1181. // ASSERT(dwInstance >= 0);
  1182. if (!IS_MASTER_INSTANCE(dwInstance))
  1183. {
  1184. TCHAR szInstance[] = _T("4000000000");
  1185. _ltot(dwInstance, szInstance, 10);
  1186. m_strMetaPath += _cszSep;
  1187. m_strMetaPath += szInstance;
  1188. }
  1189. }
  1190. void
  1191. CMetabasePath::BuildMetaPath(
  1192. IN LPCTSTR lpszSvc OPTIONAL,
  1193. IN LPCTSTR lpszInstance OPTIONAL,
  1194. IN LPCTSTR lpszParentPath OPTIONAL,
  1195. IN LPCTSTR lpszAlias OPTIONAL
  1196. )
  1197. /*++
  1198. Routine Description:
  1199. Build a complete metapath with the given service name, instance
  1200. number and optional path components.
  1201. Arguments:
  1202. LPCTSTR lpszSvc : Service (may be NULL or "")
  1203. LPCTSTR lpszInstance : Instance (may be NULL or "")
  1204. LPCTSTR lpszParentPath : Parent path (may be NULL or "")
  1205. LPCTSTR lpszAlias : Alias (may be NULL or "")
  1206. Return Value:
  1207. Pointer to internal buffer containing the path.
  1208. --*/
  1209. {
  1210. m_strMetaPath = _cszMachine;
  1211. AppendPath(lpszSvc);
  1212. AppendPath(lpszInstance);
  1213. AppendPath(lpszParentPath);
  1214. if (lpszAlias && *lpszAlias)
  1215. {
  1216. //
  1217. // Special case: If the alias is root, but we're
  1218. // at the master instance, ignore this.
  1219. //
  1220. if (lpszInstance || ::lstrcmpi(_cszRoot, lpszAlias))
  1221. {
  1222. m_strMetaPath += _cszSep;
  1223. m_strMetaPath += lpszAlias;
  1224. }
  1225. }
  1226. // TRACE(_T("Generated metapath: %s\n"), m_strMetaPath );
  1227. }
  1228. void
  1229. CMetabasePath::BuildMetaPath(
  1230. IN LPCTSTR lpszSvc OPTIONAL,
  1231. IN DWORD dwInstance OPTIONAL,
  1232. IN LPCTSTR lpszParentPath OPTIONAL,
  1233. IN LPCTSTR lpszAlias OPTIONAL
  1234. )
  1235. /*++
  1236. Routine Description:
  1237. Build a complete metapath with the given service name, instance
  1238. number and optional path components.
  1239. Arguments:
  1240. LPCTSTR lpszSvc : Service (may be NULL or "")
  1241. DWORD dwInstance : Instance number (may be 0 for master)
  1242. LPCTSTR lpszParentPath : Parent path (may be NULL or "")
  1243. LPCTSTR lpszAlias : Alias (may be NULL or "")
  1244. Return Value:
  1245. Pointer to internal buffer containing the path.
  1246. --*/
  1247. {
  1248. m_strMetaPath = _cszMachine;
  1249. AppendPath(lpszSvc);
  1250. AppendPath(dwInstance);
  1251. AppendPath(lpszParentPath);
  1252. if (lpszAlias && *lpszAlias)
  1253. {
  1254. //
  1255. // Special case: If the alias is root, but we're
  1256. // at the master instance, ignore this.
  1257. //
  1258. if (!IS_MASTER_INSTANCE(dwInstance) || ::lstrcmpi(_cszRoot, lpszAlias))
  1259. {
  1260. m_strMetaPath += _cszSep;
  1261. m_strMetaPath += lpszAlias;
  1262. }
  1263. }
  1264. // TRACE(_T("Generated metapath: %s\n"), m_strMetaPath);
  1265. }
  1266. //
  1267. // CIISInterface class
  1268. //
  1269. // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  1270. CIISInterface::CIISInterface(
  1271. IN CComAuthInfo * pAuthInfo, OPTIONAL
  1272. IN HRESULT hrInterface OPTIONAL
  1273. )
  1274. /*++
  1275. Routine Description:
  1276. Base class constructor.
  1277. Arguments:
  1278. CComAuthInfo * pAuthInfo : Auth info or NULL for local computer
  1279. HRESULT hrInterface : Initial error code. S_OK by default.
  1280. Return Value:
  1281. N/A
  1282. --*/
  1283. : m_auth(pAuthInfo),
  1284. m_hrInterface(hrInterface)
  1285. {
  1286. }
  1287. HRESULT
  1288. CIISInterface::Create(
  1289. IN int cInterfaces,
  1290. IN const IID rgIID[],
  1291. IN const GUID rgCLSID[],
  1292. OUT int * pnInterface, OPTIONAL
  1293. OUT IUnknown ** ppInterface
  1294. )
  1295. /*++
  1296. Routine Description:
  1297. Create interface. This will try a range of interfaces in order of priority.
  1298. Arguments:
  1299. int cInterfaces : Number of interfaces in array.
  1300. const IID * rgIID : Array if IIDs
  1301. const GUID * rgCLSID : Array of CLSIDs
  1302. int * pnInterface : Returns the interface index that was successful.
  1303. or NULL if not interested.
  1304. IUnknown ** ppInterface : Returns pointer to the interface.
  1305. Return Value:
  1306. HRESULT
  1307. Notes:
  1308. This will attempt to create an interface, in order of declaration in
  1309. the IID and CLSIS arrays. The first successful interface to be created
  1310. will have its index returned in *pnInterfaces.
  1311. --*/
  1312. {
  1313. ASSERT(cInterfaces > 0);
  1314. ASSERT(rgIID && rgCLSID && ppInterface);
  1315. COSERVERINFO * pcsiName = m_auth.CreateServerInfoStruct();
  1316. MULTI_QI rgmqResults;
  1317. CError err;
  1318. int nInterface;
  1319. //
  1320. // Try to create the interface in order
  1321. //
  1322. for (nInterface = 0; nInterface < cInterfaces; ++nInterface)
  1323. {
  1324. ZeroMemory(&rgmqResults, sizeof(rgmqResults));
  1325. rgmqResults.pIID = &rgIID[nInterface];
  1326. // TRACE("Attempting to create interface #%d\n", nInterface);
  1327. err = ::CoCreateInstanceEx(
  1328. rgCLSID[nInterface],
  1329. NULL,
  1330. CLSCTX_SERVER,
  1331. pcsiName,
  1332. 1,
  1333. &rgmqResults
  1334. );
  1335. if (err.Succeeded() || err.Win32Error() == ERROR_ACCESS_DENIED)
  1336. {
  1337. break;
  1338. }
  1339. }
  1340. if(err.Succeeded())
  1341. {
  1342. //
  1343. // Save the interface pointer
  1344. //
  1345. ASSERT_PTR(rgmqResults.pItf);
  1346. *ppInterface = rgmqResults.pItf;
  1347. if (pnInterface)
  1348. {
  1349. //
  1350. // Store successful interface index
  1351. //
  1352. *pnInterface = nInterface;
  1353. }
  1354. //
  1355. // Strangely enough, I now have still have to apply
  1356. // the proxy blanket. Apparently this is by design.
  1357. //
  1358. if (m_auth.UsesImpersonation())
  1359. {
  1360. ApplyProxyBlanket();
  1361. }
  1362. }
  1363. //
  1364. // Clean up
  1365. //
  1366. m_auth.FreeServerInfoStruct(pcsiName);
  1367. return err;
  1368. }
  1369. //
  1370. // CMetaInterface class
  1371. //
  1372. // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  1373. CMetaInterface::CMetaInterface(
  1374. IN CComAuthInfo * pAuthInfo OPTIONAL
  1375. )
  1376. /*++
  1377. Routine Description:
  1378. Construct and initialize the interface
  1379. Arguments:
  1380. CComAuthInfo * pAuthInfo : Authentication info. NULL indicates
  1381. the local computer.
  1382. Return Value:
  1383. N/A
  1384. --*/
  1385. : CIISInterface(pAuthInfo),
  1386. m_pInterface(NULL),
  1387. m_iTimeOutValue(MB_TIMEOUT)
  1388. {
  1389. //
  1390. // Initialize the interface
  1391. //
  1392. m_hrInterface = Create();
  1393. }
  1394. CMetaInterface::CMetaInterface(
  1395. IN CMetaInterface * pInterface
  1396. )
  1397. /*++
  1398. Routine Description:
  1399. Construct from existing interface (Copy Constructor)
  1400. Arguments:
  1401. CMetaInterface * pInterface : Existing interface
  1402. Return Value:
  1403. N/A
  1404. Notes:
  1405. Object will not take ownership of the interface,
  1406. it will merely add to the reference count, and
  1407. release it upon destruction
  1408. BUGBUG:
  1409. if pInterface is NULL, this will AV.
  1410. --*/
  1411. : CIISInterface(&pInterface->m_auth, pInterface->m_hrInterface),
  1412. m_pInterface(pInterface->m_pInterface),
  1413. m_iTimeOutValue(pInterface->m_iTimeOutValue)
  1414. {
  1415. ASSERT_READ_PTR(m_pInterface);
  1416. m_pInterface->AddRef();
  1417. }
  1418. CMetaInterface::~CMetaInterface()
  1419. /*++
  1420. Routine Description:
  1421. Destructor -- releases the interface
  1422. Arguments:
  1423. N/A
  1424. Return Value:
  1425. N/A
  1426. --*/
  1427. {
  1428. SAFE_RELEASE(m_pInterface);
  1429. }
  1430. HRESULT
  1431. CMetaInterface::Create()
  1432. {
  1433. return CIISInterface::Create(
  1434. 1,
  1435. &IID_IMSAdminBase,
  1436. &CLSID_MSAdminBase,
  1437. NULL,
  1438. (IUnknown **)&m_pInterface
  1439. );
  1440. }
  1441. //
  1442. // CMetaKey class
  1443. //
  1444. // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  1445. //
  1446. // Helper macros
  1447. //
  1448. #define ASSURE_PROPER_INTERFACE()\
  1449. if (!HasInterface()) { ASSERT_MSG("No interface"); return MD_ERROR_NOT_INITIALIZED; }
  1450. #define ASSURE_OPEN_KEY()\
  1451. if (!m_hKey && !m_fAllowRootOperations) { ASSERT_MSG("No open key"); return HRESULT_FROM_WIN32(ERROR_INVALID_HANDLE); }
  1452. #define FETCH_PROPERTY_DATA_OR_FAIL(dwID, md)\
  1453. ZeroMemory(&md, sizeof(md)); \
  1454. if (!GetMDFieldDef(dwID, md.dwMDIdentifier, md.dwMDAttributes, md.dwMDUserType, md.dwMDDataType))\
  1455. { ASSERT_MSG("Bad property ID"); return HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER); }
  1456. //
  1457. // Static Initialization
  1458. //
  1459. // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  1460. #define MD_SERVER_PLATFORM (IIS_MD_SERVER_BASE+100 )
  1461. #define MD_SERVER_VERSION_MAJOR (IIS_MD_SERVER_BASE+101 )
  1462. #define MD_SERVER_VERSION_MINOR (IIS_MD_SERVER_BASE+102 )
  1463. #define MD_SERVER_CAPABILITIES (IIS_MD_SERVER_BASE+103 )
  1464. #ifndef MD_APP_PERIODIC_RESTART_TIME
  1465. #define MD_APP_PERIODIC_RESTART_TIME 2111
  1466. #endif
  1467. #ifndef MD_APP_PERIODIC_RESTART_REQUESTS
  1468. #define MD_APP_PERIODIC_RESTART_REQUESTS 2112
  1469. #endif
  1470. #ifndef MD_APP_PERIODIC_RESTART_SCHEDULE
  1471. #define MD_APP_PERIODIC_RESTART_SCHEDULE 2113
  1472. #endif
  1473. #ifndef MD_ASP_DISKTEMPLATECACHEDIRECTORY
  1474. #define MD_ASP_DISKTEMPLATECACHEDIRECTORY 7036
  1475. #endif
  1476. #ifndef MD_ASP_MAXDISKTEMPLATECACHEFILES
  1477. #define MD_ASP_MAXDISKTEMPLATECACHEFILES 7040
  1478. #endif
  1479. //
  1480. // Metabase table
  1481. //
  1482. const CMetaKey::MDFIELDDEF CMetaKey::s_rgMetaTable[] =
  1483. {
  1484. ///////////////////////////////////////////////////////////////////////////
  1485. //
  1486. // !!!IMPORTANT!!! This table must be sorted on dwMDIdentifier. (Will
  1487. // ASSERT if not not sorted)
  1488. //
  1489. { MD_MAX_BANDWIDTH, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, DWORD_METADATA, 0 },
  1490. { MD_KEY_TYPE, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, STRING_METADATA, 0 },
  1491. { MD_SERVER_COMMAND, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, DWORD_METADATA, 0 },
  1492. { MD_CONNECTION_TIMEOUT, METADATA_INHERIT, IIS_MD_UT_SERVER, DWORD_METADATA, IDS_MD_CONNECTION_TIMEOUT },
  1493. { MD_MAX_CONNECTIONS, METADATA_INHERIT, IIS_MD_UT_SERVER, DWORD_METADATA, IDS_MD_MAX_CONNECTIONS },
  1494. { MD_SERVER_COMMENT, METADATA_INHERIT, IIS_MD_UT_SERVER, STRING_METADATA, IDS_MD_SERVER_COMMENT },
  1495. { MD_SERVER_STATE, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, DWORD_METADATA, 0 },
  1496. { MD_SERVER_AUTOSTART, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, DWORD_METADATA, 0 },
  1497. { MD_SERVER_SIZE, METADATA_INHERIT, IIS_MD_UT_SERVER, DWORD_METADATA, IDS_MD_SERVER_SIZE },
  1498. { MD_SERVER_LISTEN_BACKLOG, METADATA_INHERIT, IIS_MD_UT_SERVER, DWORD_METADATA, IDS_MD_SERVER_LISTEN_BACKLOG },
  1499. { MD_SERVER_LISTEN_TIMEOUT, METADATA_INHERIT, IIS_MD_UT_SERVER, DWORD_METADATA, IDS_MD_SERVER_LISTEN_TIMEOUT },
  1500. { MD_SERVER_BINDINGS, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, MULTISZ_METADATA, 0 },
  1501. { MD_WIN32_ERROR, METADATA_VOLATILE, IIS_MD_UT_FILE, DWORD_METADATA, 0 },
  1502. { MD_SERVER_PLATFORM, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, DWORD_METADATA, 0 },
  1503. { MD_SERVER_VERSION_MAJOR, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, DWORD_METADATA, 0 },
  1504. { MD_SERVER_VERSION_MINOR, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, DWORD_METADATA, 0 },
  1505. { MD_SERVER_CAPABILITIES, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, DWORD_METADATA, 0 },
  1506. { MD_SECURE_BINDINGS, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, MULTISZ_METADATA, 0 },
  1507. { MD_FILTER_LOAD_ORDER, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, STRING_METADATA, 0 },
  1508. { MD_FILTER_IMAGE_PATH, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, STRING_METADATA, 0 },
  1509. { MD_FILTER_STATE, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, DWORD_METADATA, 0 },
  1510. { MD_FILTER_ENABLED, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, DWORD_METADATA, 0 },
  1511. { MD_FILTER_FLAGS, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, DWORD_METADATA, 0 },
  1512. { MD_AUTH_CHANGE_URL, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, DWORD_METADATA, 0 },
  1513. { MD_AUTH_EXPIRED_URL, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, STRING_METADATA, 0 },
  1514. { MD_AUTH_NOTIFY_PWD_EXP_URL, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, STRING_METADATA, 0 },
  1515. { MD_ADV_NOTIFY_PWD_EXP_IN_DAYS, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, DWORD_METADATA, 0 },
  1516. { MD_ADV_CACHE_TTL, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, DWORD_METADATA, 0 },
  1517. { MD_AUTH_EXPIRED_UNSECUREURL, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, STRING_METADATA, 0 },
  1518. { MD_AUTH_CHANGE_FLAGS, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, DWORD_METADATA, 0 },
  1519. { MD_AUTH_NOTIFY_PWD_EXP_UNSECUREURL, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, STRING_METADATA, 0 },
  1520. { MD_FRONTPAGE_WEB, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, DWORD_METADATA, 0 },
  1521. { MD_MAPCERT, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, STRING_METADATA, 0 },
  1522. { MD_MAPNTACCT, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, STRING_METADATA, 0 },
  1523. { MD_MAPNAME, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, STRING_METADATA, 0 },
  1524. { MD_MAPENABLED, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, STRING_METADATA, 0 },
  1525. { MD_MAPREALM, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, STRING_METADATA, 0 },
  1526. { MD_MAPPWD, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, STRING_METADATA, 0 },
  1527. { MD_ITACCT, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, STRING_METADATA, 0 },
  1528. { MD_CPP_CERT11, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, BINARY_METADATA, 0 },
  1529. { MD_SERIAL_CERT11, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, BINARY_METADATA, 0 },
  1530. { MD_CPP_CERTW, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, BINARY_METADATA, 0 },
  1531. { MD_SERIAL_CERTW, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, BINARY_METADATA, 0 },
  1532. { MD_CPP_DIGEST, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, BINARY_METADATA, 0 },
  1533. { MD_SERIAL_DIGEST, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, BINARY_METADATA, 0 },
  1534. { MD_CPP_ITA, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, BINARY_METADATA, 0 },
  1535. { MD_SERIAL_ITA, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, BINARY_METADATA, 0 },
  1536. { MD_APP_FRIENDLY_NAME, METADATA_INHERIT, IIS_MD_UT_WAM, STRING_METADATA, IDS_MD_APP_FRIENDLY_NAME },
  1537. { MD_APP_ROOT, METADATA_INHERIT, IIS_MD_UT_WAM, STRING_METADATA, IDS_MD_APP_ROOT },
  1538. { MD_APP_ISOLATED, METADATA_INHERIT, IIS_MD_UT_WAM, DWORD_METADATA, IDS_MD_APP_ISOLATED },
  1539. // new stuff
  1540. { MD_APP_PERIODIC_RESTART_TIME, METADATA_INHERIT, IIS_MD_UT_WAM, DWORD_METADATA, 0 },
  1541. { MD_APP_PERIODIC_RESTART_REQUESTS, METADATA_INHERIT, IIS_MD_UT_WAM, DWORD_METADATA, 0 },
  1542. { MD_APP_PERIODIC_RESTART_SCHEDULE, METADATA_INHERIT, IIS_MD_UT_WAM, MULTISZ_METADATA, 0 },
  1543. // end new stuff
  1544. { MD_HC_COMPRESSION_DIRECTORY, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, STRING_METADATA, 0 },
  1545. { MD_HC_DO_DYNAMIC_COMPRESSION, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, DWORD_METADATA, 0 },
  1546. { MD_HC_DO_STATIC_COMPRESSION, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, DWORD_METADATA, 0 },
  1547. { MD_HC_DO_DISK_SPACE_LIMITING, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, DWORD_METADATA, 0 },
  1548. { MD_HC_MAX_DISK_SPACE_USAGE, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, DWORD_METADATA, 0 },
  1549. { MD_VR_PATH, METADATA_INHERIT, IIS_MD_UT_FILE, STRING_METADATA, IDS_MD_VR_PATH },
  1550. { MD_VR_USERNAME, METADATA_INHERIT, IIS_MD_UT_FILE, STRING_METADATA, IDS_MD_VR_USERNAME },
  1551. { MD_VR_PASSWORD, METADATA_INHERIT | METADATA_SECURE, IIS_MD_UT_FILE, STRING_METADATA, IDS_MD_VR_PASSWORD },
  1552. { MD_VR_ACL, METADATA_NO_ATTRIBUTES, IIS_MD_UT_FILE, BINARY_METADATA, 0 },
  1553. { MD_VR_UPDATE, METADATA_NO_ATTRIBUTES, IIS_MD_UT_FILE, DWORD_METADATA, 0 },
  1554. { MD_LOG_TYPE, METADATA_INHERIT, IIS_MD_UT_FILE, DWORD_METADATA, IDS_MD_LOG_TYPE },
  1555. { MD_LOGFILE_DIRECTORY, METADATA_INHERIT, IIS_MD_UT_FILE, STRING_METADATA, IDS_MD_LOGFILE_DIRECTORY },
  1556. { MD_LOGFILE_PERIOD, METADATA_INHERIT, IIS_MD_UT_FILE, DWORD_METADATA, IDS_MD_LOGFILE_PERIOD },
  1557. { MD_LOGFILE_TRUNCATE_SIZE, METADATA_INHERIT, IIS_MD_UT_FILE, DWORD_METADATA, IDS_MD_LOGFILE_TRUNCATE_SIZE },
  1558. { MD_LOGSQL_DATA_SOURCES, METADATA_INHERIT, IIS_MD_UT_FILE, STRING_METADATA, IDS_MD_LOGSQL_DATA_SOURCES },
  1559. { MD_LOGSQL_TABLE_NAME, METADATA_INHERIT, IIS_MD_UT_FILE, STRING_METADATA, IDS_MD_LOGSQL_TABLE_NAME },
  1560. { MD_LOGSQL_USER_NAME, METADATA_INHERIT, IIS_MD_UT_FILE, STRING_METADATA, IDS_MD_LOGSQL_USER_NAME },
  1561. { MD_LOGSQL_PASSWORD, METADATA_INHERIT | METADATA_SECURE, IIS_MD_UT_FILE, STRING_METADATA, IDS_MD_LOGSQL_PASSWORD },
  1562. { MD_LOG_PLUGIN_ORDER, METADATA_INHERIT, IIS_MD_UT_SERVER, STRING_METADATA, IDS_MD_LOG_PLUGIN_ORDER },
  1563. { MD_LOGEXT_FIELD_MASK, METADATA_INHERIT, IIS_MD_UT_SERVER, DWORD_METADATA, IDS_MD_LOGEXT_FIELD_MASK },
  1564. { MD_LOGFILE_LOCALTIME_ROLLOVER, METADATA_INHERIT, IIS_MD_UT_SERVER, DWORD_METADATA, IDS_MD_LOGFILE_LOCALTIME_ROLLOVER },
  1565. { MD_EXIT_MESSAGE, METADATA_INHERIT, IIS_MD_UT_SERVER, STRING_METADATA, IDS_MD_EXIT_MESSAGE },
  1566. { MD_GREETING_MESSAGE, METADATA_INHERIT, IIS_MD_UT_SERVER, MULTISZ_METADATA, IDS_MD_GREETING_MESSAGE },
  1567. { MD_MAX_CLIENTS_MESSAGE, METADATA_INHERIT, IIS_MD_UT_SERVER, STRING_METADATA, IDS_MD_MAX_CLIENTS_MESSAGE },
  1568. { MD_MSDOS_DIR_OUTPUT, METADATA_INHERIT, IIS_MD_UT_SERVER, DWORD_METADATA, IDS_MD_MSDOS_DIR_OUTPUT },
  1569. { MD_ALLOW_ANONYMOUS, METADATA_INHERIT, IIS_MD_UT_SERVER, DWORD_METADATA, IDS_MD_ALLOW_ANONYMOUS },
  1570. { MD_ANONYMOUS_ONLY, METADATA_INHERIT, IIS_MD_UT_SERVER, DWORD_METADATA, IDS_MD_ANONYMOUS_ONLY },
  1571. { MD_LOG_ANONYMOUS, METADATA_INHERIT, IIS_MD_UT_SERVER, DWORD_METADATA, IDS_MD_LOG_ANONYMOUS },
  1572. { MD_LOG_NONANONYMOUS, METADATA_INHERIT, IIS_MD_UT_SERVER, DWORD_METADATA, IDS_MD_LOG_NONANONYMOUS },
  1573. { MD_SSL_PUBLIC_KEY, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, BINARY_METADATA, 0 },
  1574. { MD_SSL_PRIVATE_KEY, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, BINARY_METADATA, 0 },
  1575. { MD_SSL_KEY_PASSWORD, METADATA_SECURE, IIS_MD_UT_SERVER, BINARY_METADATA, 0 },
  1576. { MD_SSL_CERT_HASH, METADATA_INHERIT, IIS_MD_UT_SERVER, BINARY_METADATA, 0 },
  1577. { MD_SSL_CERT_STORE_NAME, METADATA_INHERIT, IIS_MD_UT_SERVER, STRING_METADATA, 0 },
  1578. { MD_SSL_CTL_IDENTIFIER, METADATA_INHERIT, IIS_MD_UT_SERVER, STRING_METADATA, 0 },
  1579. { MD_SSL_CTL_STORE_NAME, METADATA_INHERIT, IIS_MD_UT_SERVER, STRING_METADATA, 0 },
  1580. { MD_SSL_USE_DS_MAPPER, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, DWORD_METADATA, 0 },
  1581. { MD_AUTHORIZATION, METADATA_INHERIT, IIS_MD_UT_FILE, DWORD_METADATA, IDS_MD_AUTHORIZATION },
  1582. { MD_REALM, METADATA_INHERIT, IIS_MD_UT_FILE, STRING_METADATA, IDS_MD_REALM },
  1583. { MD_HTTP_EXPIRES, METADATA_INHERIT, IIS_MD_UT_FILE, STRING_METADATA, IDS_MD_HTTP_EXPIRES },
  1584. { MD_HTTP_PICS, METADATA_INHERIT, IIS_MD_UT_FILE, MULTISZ_METADATA, IDS_MD_HTTP_PICS },
  1585. { MD_HTTP_CUSTOM, METADATA_INHERIT, IIS_MD_UT_FILE, MULTISZ_METADATA, IDS_MD_HTTP_CUSTOM },
  1586. { MD_DIRECTORY_BROWSING, METADATA_INHERIT, IIS_MD_UT_FILE, DWORD_METADATA, IDS_MD_DIRECTORY_BROWSING },
  1587. { MD_DEFAULT_LOAD_FILE, METADATA_INHERIT, IIS_MD_UT_FILE, STRING_METADATA, IDS_MD_DEFAULT_LOAD_FILE },
  1588. { MD_CONTENT_NEGOTIATION, METADATA_INHERIT, IIS_MD_UT_FILE, DWORD_METADATA, IDS_MD_CONTENT_NEGOTIATION },
  1589. { MD_CUSTOM_ERROR, METADATA_INHERIT, IIS_MD_UT_FILE, MULTISZ_METADATA, IDS_MD_CUSTOM_ERROR },
  1590. { MD_FOOTER_DOCUMENT, METADATA_INHERIT, IIS_MD_UT_FILE, STRING_METADATA, IDS_MD_FOOTER_DOCUMENT },
  1591. { MD_FOOTER_ENABLED, METADATA_INHERIT, IIS_MD_UT_FILE, DWORD_METADATA, IDS_MD_FOOTER_ENABLED },
  1592. { MD_HTTP_REDIRECT, METADATA_INHERIT, IIS_MD_UT_FILE, STRING_METADATA, IDS_MD_HTTP_REDIRECT },
  1593. { MD_DEFAULT_LOGON_DOMAIN, METADATA_INHERIT, IIS_MD_UT_FILE, STRING_METADATA, IDS_MD_DEFAULT_LOGON_DOMAIN },
  1594. { MD_LOGON_METHOD, METADATA_INHERIT, IIS_MD_UT_FILE, DWORD_METADATA, IDS_MD_LOGON_METHOD },
  1595. { MD_SCRIPT_MAPS, METADATA_INHERIT, IIS_MD_UT_FILE, MULTISZ_METADATA, IDS_MD_SCRIPT_MAPS },
  1596. { MD_MIME_MAP, METADATA_INHERIT, IIS_MD_UT_FILE, MULTISZ_METADATA, IDS_MD_MIME_MAP },
  1597. { MD_ACCESS_PERM, METADATA_INHERIT, IIS_MD_UT_FILE, DWORD_METADATA, IDS_MD_ACCESS_PERM },
  1598. { MD_IP_SEC, METADATA_INHERIT | METADATA_REFERENCE, IIS_MD_UT_FILE, BINARY_METADATA, IDS_MD_IP_SEC },
  1599. { MD_ANONYMOUS_USER_NAME, METADATA_INHERIT, IIS_MD_UT_FILE, STRING_METADATA, IDS_MD_ANONYMOUS_USER_NAME },
  1600. { MD_ANONYMOUS_PWD, METADATA_INHERIT | METADATA_SECURE, IIS_MD_UT_FILE, STRING_METADATA, IDS_MD_ANONYMOUS_PWD },
  1601. { MD_ANONYMOUS_USE_SUBAUTH, METADATA_INHERIT, IIS_MD_UT_FILE, DWORD_METADATA, IDS_MD_ANONYMOUS_USE_SUBAUTH },
  1602. { MD_DONT_LOG, METADATA_INHERIT, IIS_MD_UT_FILE, DWORD_METADATA, IDS_MD_DONT_LOG },
  1603. { MD_ADMIN_ACL, METADATA_INHERIT | METADATA_SECURE | METADATA_REFERENCE,IIS_MD_UT_SERVER, BINARY_METADATA, IDS_MD_ADMIN_ACL },
  1604. { MD_SSI_EXEC_DISABLED, METADATA_INHERIT, IIS_MD_UT_FILE, DWORD_METADATA, IDS_MD_SSI_EXEC_DISABLED },
  1605. { MD_SSL_ACCESS_PERM, METADATA_INHERIT, IIS_MD_UT_FILE, DWORD_METADATA, IDS_MD_SSL_ACCESS_PERM },
  1606. { MD_NTAUTHENTICATION_PROVIDERS, METADATA_INHERIT, IIS_MD_UT_FILE, STRING_METADATA, IDS_MD_NTAUTHENTICATION_PROVIDERS },
  1607. { MD_SCRIPT_TIMEOUT, METADATA_INHERIT, IIS_MD_UT_FILE, DWORD_METADATA, IDS_MD_SCRIPT_TIMEOUT },
  1608. { MD_CACHE_EXTENSIONS, METADATA_INHERIT, IIS_MD_UT_FILE, DWORD_METADATA, IDS_MD_CACHE_EXTENSIONS },
  1609. { MD_CREATE_PROCESS_AS_USER, METADATA_INHERIT, IIS_MD_UT_SERVER, DWORD_METADATA, IDS_MD_CREATE_PROCESS_AS_USER },
  1610. { MD_CREATE_PROC_NEW_CONSOLE, METADATA_INHERIT, IIS_MD_UT_SERVER, DWORD_METADATA, IDS_MD_CREATE_PROC_NEW_CONSOLE },
  1611. { MD_POOL_IDC_TIMEOUT, METADATA_INHERIT, IIS_MD_UT_FILE, DWORD_METADATA, IDS_MD_POOL_IDC_TIMEOUT },
  1612. { MD_ALLOW_KEEPALIVES, METADATA_INHERIT, IIS_MD_UT_FILE, DWORD_METADATA, IDS_MD_ALLOW_KEEPALIVES },
  1613. { MD_IS_CONTENT_INDEXED, METADATA_INHERIT, IIS_MD_UT_FILE, DWORD_METADATA, IDS_MD_IS_CONTENT_INDEXED },
  1614. { MD_ISM_ACCESS_CHECK, METADATA_NO_ATTRIBUTES, IIS_MD_UT_FILE, DWORD_METADATA, 0 },
  1615. { MD_ASP_BUFFERINGON, METADATA_INHERIT, ASP_MD_UT_APP, DWORD_METADATA, IDS_ASP_BUFFERINGON },
  1616. { MD_ASP_LOGERRORREQUESTS, METADATA_INHERIT, IIS_MD_UT_WAM, DWORD_METADATA, IDS_ASP_LOGERRORREQUESTS },
  1617. { MD_ASP_SCRIPTERRORSSENTTOBROWSER, METADATA_INHERIT, ASP_MD_UT_APP, DWORD_METADATA, IDS_ASP_SCRIPTERRORSSENTTOBROWSER },
  1618. { MD_ASP_SCRIPTERRORMESSAGE, METADATA_INHERIT, ASP_MD_UT_APP, STRING_METADATA, IDS_ASP_SCRIPTERRORMESSAGE },
  1619. { MD_ASP_SCRIPTFILECACHESIZE, METADATA_INHERIT, IIS_MD_UT_WAM, DWORD_METADATA, IDS_ASP_SCRIPTFILECACHESIZE },
  1620. { MD_ASP_SCRIPTENGINECACHEMAX, METADATA_INHERIT, IIS_MD_UT_WAM, DWORD_METADATA, IDS_ASP_SCRIPTENGINECACHEMAX },
  1621. { MD_ASP_SCRIPTTIMEOUT, METADATA_INHERIT, ASP_MD_UT_APP, DWORD_METADATA, IDS_ASP_SCRIPTTIMEOUT },
  1622. { MD_ASP_SESSIONTIMEOUT, METADATA_INHERIT, ASP_MD_UT_APP, DWORD_METADATA, IDS_ASP_SESSIONTIMEOUT },
  1623. { MD_ASP_ENABLEPARENTPATHS, METADATA_INHERIT, ASP_MD_UT_APP, DWORD_METADATA, IDS_ASP_ENABLEPARENTPATHS },
  1624. { MD_ASP_ALLOWSESSIONSTATE, METADATA_INHERIT, ASP_MD_UT_APP, DWORD_METADATA, IDS_ASP_ALLOWSESSIONSTATE },
  1625. { MD_ASP_SCRIPTLANGUAGE, METADATA_INHERIT, ASP_MD_UT_APP, STRING_METADATA, IDS_ASP_SCRIPTLANGUAGE },
  1626. { MD_ASP_EXCEPTIONCATCHENABLE, METADATA_INHERIT, IIS_MD_UT_WAM, DWORD_METADATA, IDS_ASP_EXCEPTIONCATCHENABLE },
  1627. { MD_ASP_ENABLESERVERDEBUG, METADATA_INHERIT, ASP_MD_UT_APP, DWORD_METADATA, IDS_ASP_ENABLESERVERDEBUG },
  1628. { MD_ASP_ENABLECLIENTDEBUG, METADATA_INHERIT, ASP_MD_UT_APP, DWORD_METADATA, IDS_ASP_ENABLECLIENTDEBUG },
  1629. { MD_ASP_DISKTEMPLATECACHEDIRECTORY, METADATA_INHERIT, IIS_MD_UT_WAM, STRING_METADATA, 0 },
  1630. { MD_ASP_MAXDISKTEMPLATECACHEFILES, METADATA_INHERIT, IIS_MD_UT_WAM, DWORD_METADATA, 0 },
  1631. { MD_WAM_USER_NAME, METADATA_INHERIT, IIS_MD_UT_WAM, STRING_METADATA, 0 },
  1632. { MD_WAM_PWD, METADATA_INHERIT, IIS_MD_UT_WAM, STRING_METADATA, 0 }
  1633. };
  1634. #define NUM_ENTRIES (sizeof(CMetaKey::s_rgMetaTable) / sizeof(CMetaKey::s_rgMetaTable[0]))
  1635. /* static */
  1636. int
  1637. CMetaKey::MapMDIDToTableIndex(
  1638. IN DWORD dwID
  1639. )
  1640. /*++
  1641. Routine Description:
  1642. Map MD id value to table index. Return -1 if not found
  1643. Arguments:
  1644. DWORD dwID : MD id value
  1645. Return Value:
  1646. Index into the table that coresponds to the MD id value
  1647. --*/
  1648. {
  1649. #ifdef _DEBUG
  1650. {
  1651. //
  1652. // Do a quick verification that our metadata
  1653. // table is sorted correctly.
  1654. //
  1655. static BOOL fTableChecked = FALSE;
  1656. if (!fTableChecked)
  1657. {
  1658. for (int n = 1; n < NUM_ENTRIES; ++n)
  1659. {
  1660. if (s_rgMetaTable[n].dwMDIdentifier
  1661. <= s_rgMetaTable[n - 1].dwMDIdentifier)
  1662. {
  1663. // TRACE("MD ID Table is out of order: Item is %d %s\n", n, s_rgMetaTable[n].dwMDIdentifier);
  1664. ASSERT_MSG("MD ID Table out of order");
  1665. }
  1666. }
  1667. //
  1668. // But only once.
  1669. //
  1670. ++fTableChecked;
  1671. }
  1672. }
  1673. #endif // _DEBUG
  1674. //
  1675. // Look up the ID in the table using a binary search
  1676. //
  1677. int nRange = NUM_ENTRIES;
  1678. int nLow = 0;
  1679. int nHigh = nRange - 1;
  1680. int nMid;
  1681. int nHalf;
  1682. while (nLow <= nHigh)
  1683. {
  1684. if (nHalf = nRange / 2)
  1685. {
  1686. nMid = nLow + (nRange & 1 ? nHalf : (nHalf - 1));
  1687. if (s_rgMetaTable[nMid].dwMDIdentifier == dwID)
  1688. {
  1689. return nMid;
  1690. }
  1691. else if (s_rgMetaTable[nMid].dwMDIdentifier > dwID)
  1692. {
  1693. nHigh = --nMid;
  1694. nRange = nRange & 1 ? nHalf : nHalf - 1;
  1695. }
  1696. else
  1697. {
  1698. nLow = ++nMid;
  1699. nRange = nHalf;
  1700. }
  1701. }
  1702. else if (nRange)
  1703. {
  1704. return s_rgMetaTable[nLow].dwMDIdentifier == dwID ? nLow : -1;
  1705. }
  1706. else
  1707. {
  1708. break;
  1709. }
  1710. }
  1711. return -1;
  1712. }
  1713. /* static */
  1714. BOOL
  1715. CMetaKey::GetMDFieldDef(
  1716. IN DWORD dwID,
  1717. OUT DWORD & dwMDIdentifier,
  1718. OUT DWORD & dwMDAttributes,
  1719. OUT DWORD & dwMDUserType,
  1720. OUT DWORD & dwMDDataType
  1721. )
  1722. /*++
  1723. Routine Description:
  1724. Get information about metabase property
  1725. Arguments:
  1726. DWORD dwID : Meta ID
  1727. DWORD & dwMDIdentifier : Meta parms
  1728. DWORD & dwMDAttributes : Meta parms
  1729. DWORD & dwMDUserType : Meta parms
  1730. DWORD & dwMDDataType : Meta parms
  1731. Return Value:
  1732. TRUE for success, FALSE for failure.
  1733. --*/
  1734. {
  1735. int nID = MapMDIDToTableIndex(dwID);
  1736. if (nID == -1)
  1737. {
  1738. //
  1739. // Unrecognized meta data ID
  1740. //
  1741. ASSERT_MSG("Unrecognized meta data id");
  1742. return FALSE;
  1743. }
  1744. dwMDIdentifier = s_rgMetaTable[nID].dwMDIdentifier;
  1745. dwMDAttributes = s_rgMetaTable[nID].dwMDAttributes;
  1746. dwMDUserType = s_rgMetaTable[nID].dwMDUserType;
  1747. dwMDDataType = s_rgMetaTable[nID].dwMDDataType;
  1748. return TRUE;
  1749. }
  1750. /* static */
  1751. BOOL
  1752. CMetaKey::IsPropertyInheritable(
  1753. IN DWORD dwID
  1754. )
  1755. /*++
  1756. Routine Description:
  1757. Check to see if the given property is inheritable
  1758. Arguments:
  1759. DWORD dwID : Metabase ID
  1760. Return Value:
  1761. TRUE if the metabase ID is inheritable, FALSE otherwise.
  1762. --*/
  1763. {
  1764. int nID = MapMDIDToTableIndex(dwID);
  1765. if (nID == -1)
  1766. {
  1767. //
  1768. // Unrecognized meta data ID
  1769. //
  1770. ASSERT_MSG("Unrecognized meta data ID");
  1771. return FALSE;
  1772. }
  1773. return (s_rgMetaTable[nID].dwMDAttributes & METADATA_INHERIT) != 0;
  1774. }
  1775. /* static */
  1776. BOOL
  1777. CMetaKey::GetPropertyDescription(
  1778. IN DWORD dwID,
  1779. OUT CString & strName
  1780. )
  1781. /*++
  1782. Routine Description:
  1783. Get a description for the given property
  1784. Arguments:
  1785. DWORD dwID : Property ID
  1786. CString & strName : Returns friendly property name
  1787. Return Value:
  1788. TRUE for success, FALSE for failure
  1789. --*/
  1790. {
  1791. int nID = MapMDIDToTableIndex(dwID);
  1792. if (nID == -1)
  1793. {
  1794. //
  1795. // Unrecognized meta data ID
  1796. //
  1797. ASSERT_MSG("Unrecognized meta data ID");
  1798. return FALSE;
  1799. }
  1800. UINT uID = s_rgMetaTable[nID].uStringID;
  1801. BOOL fResult = TRUE;
  1802. if (uID > 0)
  1803. {
  1804. fResult = (strName.LoadString(_Module.GetResourceInstance(), uID) != 0);
  1805. }
  1806. else
  1807. {
  1808. //
  1809. // Don't have a friendly name -- fake it
  1810. //
  1811. CComBSTR bstrFmt;
  1812. VERIFY(bstrFmt.LoadString(_Module.GetResourceInstance(), IDS_INHERITANCE_NO_NAME));
  1813. strName.Format(bstrFmt, dwID);
  1814. }
  1815. return fResult;
  1816. }
  1817. CMetaKey::CMetaKey(
  1818. IN CComAuthInfo * pAuthInfo OPTIONAL
  1819. )
  1820. /*++
  1821. Routine Description:
  1822. Constructor that creates the interface, but does not open the key.
  1823. This is the ONLY constructor that allows operations from
  1824. METDATA_MASTER_ROOT_HANDLE (read operations obviously)
  1825. Arguments:
  1826. CComAuthInfo * pAuthInfo : If NULL, opens interface on local machine
  1827. Return Value:
  1828. N/A
  1829. --*/
  1830. : CMetaInterface(pAuthInfo),
  1831. m_hKey(METADATA_MASTER_ROOT_HANDLE),
  1832. m_hBase(NULL),
  1833. m_hrKey(S_OK),
  1834. m_dwFlags(0L),
  1835. m_cbInitialBufferSize(MB_INIT_BUFF_SIZE),
  1836. m_strMetaPath(),
  1837. m_fAllowRootOperations(TRUE),
  1838. m_fOwnKey(TRUE)
  1839. {
  1840. m_hrKey = CMetaInterface::QueryResult();
  1841. //
  1842. // Do not open key
  1843. //
  1844. }
  1845. CMetaKey::CMetaKey(
  1846. IN CMetaInterface * pInterface
  1847. )
  1848. /*++
  1849. Routine Description:
  1850. Construct with pre-existing interface. Does not
  1851. open any keys
  1852. Arguments:
  1853. CMetaInterface * pInterface : Preexisting interface
  1854. Return Value:
  1855. N/A
  1856. --*/
  1857. : CMetaInterface(pInterface),
  1858. m_hKey(NULL),
  1859. m_hBase(NULL),
  1860. m_strMetaPath(),
  1861. m_dwFlags(0L),
  1862. m_cbInitialBufferSize(MB_INIT_BUFF_SIZE),
  1863. m_fAllowRootOperations(TRUE),
  1864. m_fOwnKey(TRUE)
  1865. {
  1866. m_hrKey = CMetaInterface::QueryResult();
  1867. }
  1868. CMetaKey::CMetaKey(
  1869. IN CComAuthInfo * pAuthInfo, OPTIONAL
  1870. IN LPCTSTR lpszMDPath, OPTIONAL
  1871. IN DWORD dwFlags,
  1872. IN METADATA_HANDLE hkBase
  1873. )
  1874. /*++
  1875. Routine Description:
  1876. Fully defined constructor that opens a key
  1877. Arguments:
  1878. CComAuthInfo * pAuthInfo : Auth info or NULL
  1879. LPCTSTR lpszMDPath : Path or NULL
  1880. DWORD dwFlags : Open permissions
  1881. METADATA_HANDLE hkBase : Base key
  1882. Return Value:
  1883. N/A
  1884. --*/
  1885. : CMetaInterface(pAuthInfo),
  1886. // : CMetaInterface((CComAuthInfo *)NULL),
  1887. m_hKey(NULL),
  1888. m_hBase(NULL),
  1889. m_dwFlags(0L),
  1890. m_cbInitialBufferSize(MB_INIT_BUFF_SIZE),
  1891. m_fAllowRootOperations(FALSE),
  1892. m_strMetaPath(),
  1893. m_fOwnKey(TRUE)
  1894. {
  1895. m_hrKey = CMetaInterface::QueryResult();
  1896. if (SUCCEEDED(m_hrKey))
  1897. {
  1898. m_hrKey = Open(dwFlags, lpszMDPath, hkBase);
  1899. }
  1900. }
  1901. CMetaKey::CMetaKey(
  1902. IN CMetaInterface * pInterface,
  1903. IN LPCTSTR lpszMDPath, OPTIONAL
  1904. IN DWORD dwFlags,
  1905. IN METADATA_HANDLE hkBase
  1906. )
  1907. /*++
  1908. Routine Description:
  1909. Fully defined constructor that opens a key
  1910. Arguments:
  1911. CMetaInterface * pInterface : Existing interface
  1912. DWORD dwFlags : Open permissions
  1913. METADATA_HANDLE hkBase : Base key
  1914. LPCTSTR lpszMDPath : Path or NULL
  1915. Return Value:
  1916. N/A
  1917. --*/
  1918. : CMetaInterface(pInterface),
  1919. m_hKey(NULL),
  1920. m_hBase(NULL),
  1921. m_strMetaPath(),
  1922. m_dwFlags(0L),
  1923. m_cbInitialBufferSize(MB_INIT_BUFF_SIZE),
  1924. m_fAllowRootOperations(FALSE),
  1925. m_fOwnKey(TRUE)
  1926. {
  1927. m_hrKey = CMetaInterface::QueryResult();
  1928. if (SUCCEEDED(m_hrKey))
  1929. {
  1930. m_hrKey = Open(dwFlags, lpszMDPath, hkBase);
  1931. }
  1932. }
  1933. CMetaKey::CMetaKey(
  1934. IN BOOL fOwnKey,
  1935. IN CMetaKey * pKey
  1936. )
  1937. /*++
  1938. Routine Description:
  1939. Copy constructor.
  1940. Arguments:
  1941. BOOL fOwnKey : TRUE to take ownership of the key
  1942. const CMetaKey * pKey : Existing key
  1943. Return Value:
  1944. N/A
  1945. --*/
  1946. : CMetaInterface(pKey),
  1947. m_hKey(pKey->m_hKey),
  1948. m_hBase(pKey->m_hBase),
  1949. m_dwFlags(pKey->m_dwFlags),
  1950. m_cbInitialBufferSize(pKey->m_cbInitialBufferSize),
  1951. m_fAllowRootOperations(pKey->m_fAllowRootOperations),
  1952. m_hrKey(pKey->m_hrKey),
  1953. m_strMetaPath(pKey->m_strMetaPath),
  1954. m_fOwnKey(fOwnKey)
  1955. {
  1956. //
  1957. // No provisions for anything else at the moment
  1958. //
  1959. ASSERT(!m_fOwnKey);
  1960. }
  1961. CMetaKey::~CMetaKey()
  1962. /*++
  1963. Routine Description:
  1964. Destructor -- Close the key.
  1965. Arguments:
  1966. N/A
  1967. Return Value:
  1968. N/A
  1969. --*/
  1970. {
  1971. if (IsOpen() && m_fOwnKey)
  1972. {
  1973. Close();
  1974. }
  1975. }
  1976. /* virtual */
  1977. BOOL
  1978. CMetaKey::Succeeded() const
  1979. /*++
  1980. Routine Description:
  1981. Determine if object was constructed successfully
  1982. Arguments:
  1983. None
  1984. Return Value:
  1985. TRUE for success, FALSE for failure
  1986. --*/
  1987. {
  1988. return SUCCEEDED(m_hrKey);
  1989. }
  1990. /* virtual */
  1991. HRESULT
  1992. CMetaKey::QueryResult() const
  1993. /*++
  1994. Routine Description:
  1995. Return the construction error for this object
  1996. Arguments:
  1997. None
  1998. Return Value:
  1999. HRESULT from construction errors
  2000. --*/
  2001. {
  2002. return m_hrKey;
  2003. }
  2004. HRESULT
  2005. CMetaKey::Open(
  2006. IN DWORD dwFlags,
  2007. IN LPCTSTR lpszMDPath, OPTIONAL
  2008. IN METADATA_HANDLE hkBase
  2009. )
  2010. /*++
  2011. Routine Description:
  2012. Attempt to open a metabase key
  2013. Arguments:
  2014. DWORD dwFlags : Permission flags
  2015. LPCTSTR lpszMDPath : Optional path
  2016. METADATA_HANDLE hkBase : Base metabase key
  2017. Return Value:
  2018. HRESULT
  2019. --*/
  2020. {
  2021. ASSURE_PROPER_INTERFACE();
  2022. if (m_hKey != NULL)
  2023. {
  2024. ASSERT_MSG("Attempting to open key that already has an open handle");
  2025. // TRACEEOLID("Closing that key");
  2026. Close();
  2027. }
  2028. //
  2029. // Base key is stored for reopen purposes only
  2030. //
  2031. m_hBase = hkBase;
  2032. m_strMetaPath = lpszMDPath;
  2033. m_dwFlags = dwFlags;
  2034. return OpenKey(m_hBase, m_strMetaPath, m_dwFlags, &m_hKey);
  2035. }
  2036. HRESULT
  2037. CMetaKey::CreatePathFromFailedOpen()
  2038. /*++
  2039. Routine Description:
  2040. If the path doesn't exist, create it. This method should be
  2041. called after an Open call failed (because it will have initialized
  2042. m_strMetaPath.
  2043. Arguments:
  2044. None
  2045. Return Value:
  2046. HRESULT
  2047. --*/
  2048. {
  2049. CString strParentPath;
  2050. CString strObjectName;
  2051. CString strSavePath(m_strMetaPath);
  2052. CMetabasePath::SplitMetaPathAtInstance(
  2053. m_strMetaPath,
  2054. strParentPath,
  2055. strObjectName
  2056. );
  2057. CError err(Open(
  2058. METADATA_PERMISSION_WRITE,
  2059. strParentPath
  2060. ));
  2061. if (err.Succeeded())
  2062. {
  2063. //
  2064. // This really should never fail, because we're opening
  2065. // the path at the instance.
  2066. //
  2067. err = AddKey(strObjectName);
  2068. }
  2069. if (IsOpen())
  2070. {
  2071. Close();
  2072. }
  2073. //
  2074. // The previous open wiped out the path...
  2075. //
  2076. m_strMetaPath = strSavePath;
  2077. return err;
  2078. }
  2079. HRESULT
  2080. CMetaKey::Close()
  2081. /*++
  2082. Routine Description:
  2083. Close the currently open key.
  2084. Arguments:
  2085. N/A
  2086. Return Value:
  2087. N/A
  2088. --*/
  2089. {
  2090. ASSURE_PROPER_INTERFACE();
  2091. HRESULT hr = S_OK;
  2092. ASSERT(m_hKey != NULL);
  2093. ASSERT(m_fOwnKey);
  2094. if (m_hKey)
  2095. {
  2096. hr = CloseKey(m_hKey);
  2097. if (SUCCEEDED(hr))
  2098. {
  2099. m_hKey = NULL;
  2100. }
  2101. }
  2102. return hr;
  2103. }
  2104. HRESULT
  2105. CMetaKey::ConvertToParentPath(
  2106. IN BOOL fImmediate
  2107. )
  2108. /*++
  2109. Routine Description:
  2110. Change the path to the parent path.
  2111. Arguments:
  2112. BOOL fImmediate : If TRUE, the immediate parent's path will be used
  2113. if FALSE, the first parent that really exists
  2114. Return Value:
  2115. HRESULT
  2116. ERROR_INVALID_PARAMETER if there is no valid path
  2117. --*/
  2118. {
  2119. BOOL fIsOpen = IsOpen();
  2120. if (fIsOpen)
  2121. {
  2122. Close();
  2123. }
  2124. CError err;
  2125. FOREVER
  2126. {
  2127. if (!CMetabasePath::ConvertToParentPath(m_strMetaPath))
  2128. {
  2129. //
  2130. // There is no parent path
  2131. //
  2132. err = ERROR_INVALID_PARAMETER;
  2133. break;
  2134. }
  2135. err = ReOpen();
  2136. //
  2137. // Path not found is the only valid error
  2138. // other than success.
  2139. //
  2140. if (fImmediate
  2141. || err.Succeeded()
  2142. || err.Win32Error() != ERROR_PATH_NOT_FOUND)
  2143. {
  2144. break;
  2145. }
  2146. }
  2147. //
  2148. // Remember to reset the construction error
  2149. // which referred to the parent path.
  2150. //
  2151. m_hrKey = err;
  2152. return err;
  2153. }
  2154. /* protected */
  2155. HRESULT
  2156. CMetaKey::GetPropertyValue(
  2157. IN DWORD dwID,
  2158. OUT IN DWORD & dwSize, OPTIONAL
  2159. OUT IN void *& pvData, OPTIONAL
  2160. OUT IN DWORD * pdwDataType, OPTIONAL
  2161. IN BOOL * pfInheritanceOverride, OPTIONAL
  2162. IN LPCTSTR lpszMDPath, OPTIONAL
  2163. OUT DWORD * pdwAttributes OPTIONAL
  2164. )
  2165. /*++
  2166. Routine Description:
  2167. Get metadata on the currently open key.
  2168. Arguments:
  2169. DWORD dwID : Property ID number
  2170. DWORD & dwSize : Buffer size (could be 0)
  2171. void *& pvData : Buffer -- will allocate if NULL
  2172. DWORD * pdwDataType : NULL or on in contains valid data types,
  2173. : on out contains actual data type
  2174. BOOL * pfInheritanceOverride : NULL or on forces inheritance on/off
  2175. LPCTSTR lpszMDPath : Optional path off the open key
  2176. DWORD * pdwAttributes : Optionally returns attributes
  2177. Return Value:
  2178. HRESULT
  2179. ERROR_INVALID_HANDLE : If the handle is not open
  2180. ERROR_INVALID_PARAMETER : If the property id is not found,
  2181. or the data type doesn't match requested type
  2182. ERROR_OUTOFMEMORY : Out of memory
  2183. --*/
  2184. {
  2185. ASSURE_PROPER_INTERFACE();
  2186. ASSURE_OPEN_KEY();
  2187. METADATA_RECORD mdRecord;
  2188. FETCH_PROPERTY_DATA_OR_FAIL(dwID, mdRecord);
  2189. //
  2190. // If unable to find this property ID in our table, or
  2191. // if we specified a desired type, and this type doesn't
  2192. // match it, give up.
  2193. //
  2194. if (pdwDataType && *pdwDataType != ALL_METADATA
  2195. && *pdwDataType != mdRecord.dwMDDataType)
  2196. {
  2197. ASSERT_MSG("Invalid parameter");
  2198. return HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER);
  2199. }
  2200. //
  2201. // Check to see if inheritance behaviour is overridden
  2202. //
  2203. if (pfInheritanceOverride)
  2204. {
  2205. if (*pfInheritanceOverride)
  2206. {
  2207. mdRecord.dwMDAttributes |= METADATA_INHERIT;
  2208. }
  2209. else
  2210. {
  2211. mdRecord.dwMDAttributes &= ~METADATA_INHERIT;
  2212. }
  2213. }
  2214. //
  2215. // This causes a bad parameter error on input otherwise
  2216. //
  2217. mdRecord.dwMDAttributes &= ~METADATA_REFERENCE;
  2218. //
  2219. // If we're looking for inheritable properties, the path
  2220. // doesn't have to be completely specified.
  2221. //
  2222. if (mdRecord.dwMDAttributes & METADATA_INHERIT)
  2223. {
  2224. mdRecord.dwMDAttributes |= (METADATA_PARTIAL_PATH | METADATA_ISINHERITED);
  2225. }
  2226. ASSERT(dwSize > 0 || pvData == NULL);
  2227. mdRecord.dwMDDataLen = dwSize;
  2228. mdRecord.pbMDData = (LPBYTE)pvData;
  2229. //
  2230. // If no buffer provided, allocate one.
  2231. //
  2232. HRESULT hr = S_OK;
  2233. BOOL fBufferTooSmall = FALSE;
  2234. BOOL fAllocatedMemory = FALSE;
  2235. DWORD dwInitSize = m_cbInitialBufferSize;
  2236. do
  2237. {
  2238. if(mdRecord.pbMDData == NULL)
  2239. {
  2240. mdRecord.dwMDDataLen = dwInitSize;
  2241. mdRecord.pbMDData = new BYTE[dwInitSize];
  2242. if(mdRecord.pbMDData == NULL && dwInitSize > 0)
  2243. {
  2244. hr = HRESULT_FROM_WIN32(ERROR_OUTOFMEMORY);
  2245. break;
  2246. }
  2247. ++fAllocatedMemory;
  2248. }
  2249. //
  2250. // Get the data
  2251. //
  2252. DWORD dwRequiredDataLen = 0;
  2253. hr = GetData(m_hKey, lpszMDPath, &mdRecord, &dwRequiredDataLen);
  2254. //
  2255. // Re-fetch the buffer if it's too small.
  2256. //
  2257. fBufferTooSmall =
  2258. (HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER) && fAllocatedMemory;
  2259. if(fBufferTooSmall)
  2260. {
  2261. //
  2262. // Delete the old buffer, and set up for a re-fetch.
  2263. //
  2264. delete [] mdRecord.pbMDData;
  2265. mdRecord.pbMDData = NULL;
  2266. dwInitSize = dwRequiredDataLen;
  2267. }
  2268. }
  2269. while(fBufferTooSmall);
  2270. //
  2271. // Failed
  2272. //
  2273. if (FAILED(hr) && fAllocatedMemory)
  2274. {
  2275. delete [] mdRecord.pbMDData;
  2276. mdRecord.pbMDData = NULL;
  2277. }
  2278. dwSize = mdRecord.dwMDDataLen;
  2279. pvData = mdRecord.pbMDData;
  2280. if (pdwDataType != NULL)
  2281. {
  2282. //
  2283. // Return actual data type
  2284. //
  2285. *pdwDataType = mdRecord.dwMDDataType;
  2286. }
  2287. if (pdwAttributes != NULL)
  2288. {
  2289. //
  2290. // Return data attributes
  2291. //
  2292. *pdwAttributes = mdRecord.dwMDAttributes;
  2293. }
  2294. return hr;
  2295. }
  2296. /* protected */
  2297. HRESULT
  2298. CMetaKey::GetDataPaths(
  2299. OUT CStringListEx & strlDataPaths,
  2300. IN DWORD dwMDIdentifier,
  2301. IN DWORD dwMDDataType,
  2302. IN LPCTSTR lpszMDPath OPTIONAL
  2303. )
  2304. /*++
  2305. Routine Description:
  2306. Get data paths
  2307. Arguments:
  2308. Return Value:
  2309. HRESULT
  2310. --*/
  2311. {
  2312. ASSURE_PROPER_INTERFACE();
  2313. ASSURE_OPEN_KEY();
  2314. //
  2315. // Start with a small buffer
  2316. //
  2317. DWORD dwMDBufferSize = 1024;
  2318. LPTSTR lpszBuffer = NULL;
  2319. CError err;
  2320. do
  2321. {
  2322. delete [] lpszBuffer;
  2323. lpszBuffer = new TCHAR[dwMDBufferSize];
  2324. if (lpszBuffer == NULL)
  2325. {
  2326. err = ERROR_NOT_ENOUGH_MEMORY;
  2327. break;
  2328. }
  2329. err = CMetaInterface::GetDataPaths(
  2330. m_hKey,
  2331. lpszMDPath,
  2332. dwMDIdentifier,
  2333. dwMDDataType,
  2334. dwMDBufferSize,
  2335. lpszBuffer,
  2336. &dwMDBufferSize
  2337. );
  2338. }
  2339. while(err.Win32Error() == ERROR_INSUFFICIENT_BUFFER);
  2340. if (err.Win32Error() == ERROR_PATH_NOT_FOUND)
  2341. {
  2342. //
  2343. // That's ok... this is some sort of physical directory
  2344. // that doesn't currently exist in the metabase, and
  2345. // which therefore doesn't have any descendants anyway.
  2346. //
  2347. ZeroMemory(lpszBuffer, dwMDBufferSize);
  2348. err.Reset();
  2349. }
  2350. if (err.Succeeded())
  2351. {
  2352. strlDataPaths.ConvertFromDoubleNullList(lpszBuffer);
  2353. delete [] lpszBuffer;
  2354. }
  2355. return err;
  2356. }
  2357. HRESULT
  2358. CMetaKey::CheckDescendants(
  2359. IN DWORD dwID,
  2360. IN CComAuthInfo * pAuthInfo, OPTIONAL
  2361. IN LPCTSTR lpszMDPath OPTIONAL
  2362. )
  2363. /*++
  2364. Routine Description:
  2365. Check for descendant overrides; If there are any, bring up a dialog
  2366. that displays them, and give the user the opportunity the remove
  2367. the overrides.
  2368. Arguments:
  2369. DWORD dwID : Property ID
  2370. CComAuthInfo * pAuthInfo : Server or NULL
  2371. LPCTSTR lpszMDPath : Metabase path or NULL
  2372. Return Value:
  2373. HRESULT
  2374. --*/
  2375. {
  2376. ASSURE_PROPER_INTERFACE();
  2377. HRESULT hr = S_OK;
  2378. METADATA_RECORD mdRecord;
  2379. FETCH_PROPERTY_DATA_OR_FAIL(dwID, mdRecord);
  2380. if (mdRecord.dwMDAttributes & METADATA_INHERIT)
  2381. {
  2382. CStringListEx strlDataPaths;
  2383. hr = GetDataPaths(
  2384. strlDataPaths,
  2385. mdRecord.dwMDIdentifier,
  2386. mdRecord.dwMDDataType,
  2387. lpszMDPath
  2388. );
  2389. if (SUCCEEDED(hr) && !strlDataPaths.empty())
  2390. {
  2391. //
  2392. // Bring up the inheritance override dialog
  2393. //
  2394. CInheritanceDlg dlg(
  2395. dwID,
  2396. FROM_WRITE_PROPERTY,
  2397. pAuthInfo,
  2398. lpszMDPath,
  2399. strlDataPaths
  2400. );
  2401. if (!dlg.IsEmpty())
  2402. {
  2403. dlg.DoModal();
  2404. }
  2405. }
  2406. }
  2407. return hr;
  2408. }
  2409. /* protected */
  2410. HRESULT
  2411. CMetaKey::SetPropertyValue(
  2412. IN DWORD dwID,
  2413. IN DWORD dwSize,
  2414. IN void * pvData,
  2415. IN BOOL * pfInheritanceOverride, OPTIONAL
  2416. IN LPCTSTR lpszMDPath OPTIONAL
  2417. )
  2418. /*++
  2419. Routine Description:
  2420. Set metadata on the open key. The key must have been opened with
  2421. write permission.
  2422. Arguments:
  2423. DWORD dwID : Property ID
  2424. DWORD dwSize : Size of data
  2425. void * pvData : Data buffer
  2426. BOOL * pfInheritanceOverride : NULL or forces inheritance on/off
  2427. LPCTSTR lpszMDPath : Optional path off the open key
  2428. Return Value:
  2429. HRESULT
  2430. ERROR_INVALID_HANDLE : If the handle is not open
  2431. ERROR_INVALID_PARAMETER : If the property id is not found,
  2432. or the buffer is NULL or of size 0
  2433. --*/
  2434. {
  2435. ASSURE_PROPER_INTERFACE();
  2436. ASSURE_OPEN_KEY();
  2437. if (pvData == NULL && dwSize != 0)
  2438. {
  2439. ASSERT_MSG("No Data");
  2440. return HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER);
  2441. }
  2442. METADATA_RECORD mdRecord;
  2443. FETCH_PROPERTY_DATA_OR_FAIL(dwID, mdRecord);
  2444. if (pfInheritanceOverride)
  2445. {
  2446. if (*pfInheritanceOverride)
  2447. {
  2448. mdRecord.dwMDAttributes |= METADATA_INHERIT;
  2449. }
  2450. else
  2451. {
  2452. mdRecord.dwMDAttributes &= ~METADATA_INHERIT;
  2453. }
  2454. }
  2455. mdRecord.dwMDDataLen = dwSize;
  2456. mdRecord.pbMDData = (LPBYTE)pvData;
  2457. return SetData(m_hKey, lpszMDPath, &mdRecord);
  2458. }
  2459. /* protected */
  2460. HRESULT
  2461. CMetaKey::GetAllData(
  2462. IN DWORD dwMDAttributes,
  2463. IN DWORD dwMDUserType,
  2464. IN DWORD dwMDDataType,
  2465. OUT DWORD * pdwMDNumEntries,
  2466. OUT DWORD * pdwMDDataLen,
  2467. OUT PBYTE * ppbMDData,
  2468. IN LPCTSTR lpszMDPath OPTIONAL
  2469. )
  2470. /*++
  2471. Routine Description:
  2472. Get all data off the open key. Buffer is created automatically.
  2473. Arguments:
  2474. DWORD dwMDAttributes : Attributes
  2475. DWORD dwMDUserType : User type to fetch
  2476. DWORD dwMDDataType : Data type to fetch
  2477. DWORD * pdwMDNumEntries : Returns number of entries read
  2478. DWORD * pdwMDDataLen : Returns size of data buffer
  2479. PBYTE * ppbMDData : Returns data buffer
  2480. LPCTSTR lpszMDPath : Optional data path
  2481. Return Value:
  2482. HRESULT
  2483. --*/
  2484. {
  2485. ASSURE_PROPER_INTERFACE();
  2486. ASSURE_OPEN_KEY();
  2487. //
  2488. // Check for valid parameters
  2489. //
  2490. if(!pdwMDDataLen || !ppbMDData || !pdwMDNumEntries)
  2491. {
  2492. return HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER);
  2493. }
  2494. HRESULT hr = S_OK;
  2495. BOOL fBufferTooSmall = FALSE;
  2496. DWORD dwMDDataSetNumber;
  2497. DWORD dwRequiredBufferSize;
  2498. DWORD dwInitSize = m_cbInitialBufferSize;
  2499. *ppbMDData = NULL;
  2500. do
  2501. {
  2502. *pdwMDDataLen = dwInitSize;
  2503. *ppbMDData = new BYTE[dwInitSize];
  2504. if (ppbMDData == NULL && dwInitSize > 0)
  2505. {
  2506. hr = HRESULT_FROM_WIN32(ERROR_OUTOFMEMORY);
  2507. break;
  2508. }
  2509. hr = CMetaInterface::GetAllData(
  2510. m_hKey,
  2511. lpszMDPath,
  2512. dwMDAttributes,
  2513. dwMDUserType,
  2514. dwMDDataType,
  2515. pdwMDNumEntries,
  2516. &dwMDDataSetNumber,
  2517. *pdwMDDataLen,
  2518. *ppbMDData,
  2519. &dwRequiredBufferSize
  2520. );
  2521. //
  2522. // Re-fetch the buffer if it's too small.
  2523. //
  2524. fBufferTooSmall = (HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER);
  2525. if(fBufferTooSmall)
  2526. {
  2527. //
  2528. // Delete the old buffer, and set up for a re-fetch.
  2529. //
  2530. delete [] *ppbMDData;
  2531. dwInitSize = dwRequiredBufferSize;
  2532. }
  2533. }
  2534. while (fBufferTooSmall);
  2535. if (FAILED(hr))
  2536. {
  2537. //
  2538. // No good, be sure we don't leak anything
  2539. //
  2540. delete [] *ppbMDData;
  2541. dwInitSize = 0L;
  2542. }
  2543. return hr;
  2544. }
  2545. HRESULT
  2546. CMetaKey::QueryValue(
  2547. IN DWORD dwID,
  2548. IN OUT DWORD & dwValue,
  2549. IN BOOL * pfInheritanceOverride, OPTIONAL
  2550. IN LPCTSTR lpszMDPath, OPTIONAL
  2551. OUT DWORD * pdwAttributes OPTIONAL
  2552. )
  2553. /*++
  2554. Routine Description:
  2555. Fetch data as a DWORD
  2556. Arguments:
  2557. DWORD dwID : Property ID
  2558. DWORD & dwValue : Returns the value read in
  2559. BOOL * pfInheritanceOverride : NULL or forces inheritance on/off
  2560. LPCTSTR lpszMDPath : Optional path off the open key
  2561. DWORD * pdwAttributes : Optionally returns attributes
  2562. Return Value:
  2563. HRESULT
  2564. --*/
  2565. {
  2566. DWORD dwSize = sizeof(dwValue);
  2567. DWORD dwDataType = DWORD_METADATA;
  2568. void * pvData = &dwValue;
  2569. return GetPropertyValue(
  2570. dwID,
  2571. dwSize,
  2572. pvData,
  2573. &dwDataType,
  2574. pfInheritanceOverride,
  2575. lpszMDPath,
  2576. pdwAttributes
  2577. );
  2578. }
  2579. HRESULT
  2580. CMetaKey::QueryValue(
  2581. IN DWORD dwID,
  2582. IN OUT CString & strValue,
  2583. IN BOOL * pfInheritanceOverride, OPTIONAL
  2584. IN LPCTSTR lpszMDPath, OPTIONAL
  2585. OUT DWORD * pdwAttributes OPTIONAL
  2586. )
  2587. /*++
  2588. Routine Description:
  2589. Fetch data as a string
  2590. Arguments:
  2591. DWORD dwID : Property ID
  2592. DWORD & strValue : Returns the value read in
  2593. BOOL * pfInheritanceOverride : NULL or forces inheritance on/off
  2594. LPCTSTR lpszMDPath : Optional path off the open key
  2595. DWORD * pdwAttributes : Optionally returns attributes
  2596. Return Value:
  2597. HRESULT
  2598. --*/
  2599. {
  2600. //
  2601. // Get GetData allocate the buffer for us
  2602. //
  2603. DWORD dwSize = 0;
  2604. DWORD dwDataType = ALL_METADATA;
  2605. LPTSTR lpData = NULL;
  2606. HRESULT hr = GetPropertyValue(
  2607. dwID,
  2608. dwSize,
  2609. (void *&)lpData,
  2610. &dwDataType,
  2611. pfInheritanceOverride,
  2612. lpszMDPath,
  2613. pdwAttributes
  2614. );
  2615. if (SUCCEEDED(hr))
  2616. {
  2617. //
  2618. // Notes: consider optional auto-expansion on EXPANDSZ_METADATA
  2619. // (see registry functions), and data type conversions for DWORD
  2620. // or MULTISZ_METADATA or BINARY_METADATA
  2621. //
  2622. if (dwDataType == EXPANDSZ_METADATA || dwDataType == STRING_METADATA)
  2623. {
  2624. try
  2625. {
  2626. strValue = lpData;
  2627. }
  2628. catch(std::bad_alloc)
  2629. {
  2630. hr = HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
  2631. }
  2632. }
  2633. else
  2634. {
  2635. hr = HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER);
  2636. }
  2637. }
  2638. if (lpData)
  2639. {
  2640. delete [] lpData;
  2641. }
  2642. return hr;
  2643. }
  2644. HRESULT
  2645. CMetaKey::QueryValue(
  2646. IN DWORD dwID,
  2647. IN OUT CStrPassword & strValue,
  2648. IN BOOL * pfInheritanceOverride, OPTIONAL
  2649. IN LPCTSTR lpszMDPath, OPTIONAL
  2650. OUT DWORD * pdwAttributes OPTIONAL
  2651. )
  2652. /*++
  2653. Routine Description:
  2654. Fetch data as a string
  2655. Arguments:
  2656. DWORD dwID : Property ID
  2657. CStrPassword & strValue : Returns the value read in
  2658. BOOL * pfInheritanceOverride : NULL or forces inheritance on/off
  2659. LPCTSTR lpszMDPath : Optional path off the open key
  2660. DWORD * pdwAttributes : Optionally returns attributes
  2661. Return Value:
  2662. HRESULT
  2663. --*/
  2664. {
  2665. //
  2666. // Get GetData allocate the buffer for us
  2667. //
  2668. DWORD dwSize = 0;
  2669. DWORD dwDataType = ALL_METADATA;
  2670. LPTSTR lpData = NULL;
  2671. HRESULT hr = GetPropertyValue(
  2672. dwID,
  2673. dwSize,
  2674. (void *&)lpData,
  2675. &dwDataType,
  2676. pfInheritanceOverride,
  2677. lpszMDPath,
  2678. pdwAttributes
  2679. );
  2680. if (SUCCEEDED(hr))
  2681. {
  2682. //
  2683. // Notes: consider optional auto-expansion on EXPANDSZ_METADATA
  2684. // (see registry functions), and data type conversions for DWORD
  2685. // or MULTISZ_METADATA or BINARY_METADATA
  2686. //
  2687. if (dwDataType == EXPANDSZ_METADATA || dwDataType == STRING_METADATA)
  2688. {
  2689. try
  2690. {
  2691. strValue = lpData;
  2692. }
  2693. catch(std::bad_alloc)
  2694. {
  2695. hr = HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
  2696. }
  2697. }
  2698. else
  2699. {
  2700. hr = HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER);
  2701. }
  2702. }
  2703. if (lpData)
  2704. {
  2705. delete [] lpData;
  2706. }
  2707. return hr;
  2708. }
  2709. HRESULT
  2710. CMetaKey::QueryValue(
  2711. IN DWORD dwID,
  2712. IN OUT CComBSTR & strValue,
  2713. IN BOOL * pfInheritanceOverride, OPTIONAL
  2714. IN LPCTSTR lpszMDPath, OPTIONAL
  2715. OUT DWORD * pdwAttributes OPTIONAL
  2716. )
  2717. /*++
  2718. Routine Description:
  2719. Fetch data as a string
  2720. Arguments:
  2721. DWORD dwID : Property ID
  2722. DWORD & CComBSTR : Returns the value read in
  2723. BOOL * pfInheritanceOverride : NULL or forces inheritance on/off
  2724. LPCTSTR lpszMDPath : Optional path off the open key
  2725. DWORD * pdwAttributes : Optionally returns attributes
  2726. Return Value:
  2727. HRESULT
  2728. --*/
  2729. {
  2730. //
  2731. // Get GetData allocate the buffer for us
  2732. //
  2733. DWORD dwSize = 0;
  2734. DWORD dwDataType = ALL_METADATA;
  2735. LPTSTR lpData = NULL;
  2736. HRESULT hr = GetPropertyValue(
  2737. dwID,
  2738. dwSize,
  2739. (void *&)lpData,
  2740. &dwDataType,
  2741. pfInheritanceOverride,
  2742. lpszMDPath,
  2743. pdwAttributes
  2744. );
  2745. if (SUCCEEDED(hr))
  2746. {
  2747. //
  2748. // Notes: consider optional auto-expansion on EXPANDSZ_METADATA
  2749. // (see registry functions), and data type conversions for DWORD
  2750. // or MULTISZ_METADATA or BINARY_METADATA
  2751. //
  2752. if (dwDataType == EXPANDSZ_METADATA || dwDataType == STRING_METADATA)
  2753. {
  2754. strValue = lpData;
  2755. }
  2756. else
  2757. {
  2758. hr = HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER);
  2759. }
  2760. }
  2761. if (lpData)
  2762. {
  2763. delete [] lpData;
  2764. }
  2765. return hr;
  2766. }
  2767. HRESULT
  2768. CMetaKey::QueryValue(
  2769. IN DWORD dwID,
  2770. IN OUT CStringListEx & strlValue,
  2771. IN BOOL * pfInheritanceOverride, OPTIONAL
  2772. IN LPCTSTR lpszMDPath, OPTIONAL
  2773. OUT DWORD * pdwAttributes OPTIONAL
  2774. )
  2775. /*++
  2776. Routine Description:
  2777. Fetch data as a stringlist
  2778. Arguments:
  2779. DWORD dwID : Property ID
  2780. DWORD & strlValue : Returns the value read in
  2781. BOOL * pfInheritanceOverride : NULL or forces inheritance on/off
  2782. LPCTSTR lpszMDPath : Optional path off the open key
  2783. DWORD * pdwAttributes : Optionally returns attributes
  2784. Return Value:
  2785. HRESULT
  2786. --*/
  2787. {
  2788. //
  2789. // Get GetData allocate the buffer for us
  2790. //
  2791. DWORD dwSize = 0;
  2792. DWORD dwDataType = MULTISZ_METADATA;
  2793. LPTSTR lpData = NULL;
  2794. HRESULT hr = GetPropertyValue(
  2795. dwID,
  2796. dwSize,
  2797. (void *&)lpData,
  2798. &dwDataType,
  2799. pfInheritanceOverride,
  2800. lpszMDPath,
  2801. pdwAttributes
  2802. );
  2803. if (SUCCEEDED(hr))
  2804. {
  2805. //
  2806. // Notes: Consider accepting a single STRING
  2807. //
  2808. ASSERT(dwDataType == MULTISZ_METADATA);
  2809. DWORD err = strlValue.ConvertFromDoubleNullList(lpData, dwSize / sizeof(TCHAR));
  2810. hr = HRESULT_FROM_WIN32(err);
  2811. }
  2812. if (lpData)
  2813. {
  2814. delete [] lpData;
  2815. }
  2816. return hr;
  2817. }
  2818. HRESULT
  2819. CMetaKey::QueryValue(
  2820. IN DWORD dwID,
  2821. IN OUT CBlob & blValue,
  2822. IN BOOL * pfInheritanceOverride, OPTIONAL
  2823. IN LPCTSTR lpszMDPath, OPTIONAL
  2824. OUT DWORD * pdwAttributes OPTIONAL
  2825. )
  2826. /*++
  2827. Routine Description:
  2828. Fetch data as a binary blob
  2829. Arguments:
  2830. DWORD dwID : Property ID
  2831. DWORD CBlob & blValue : Returns the binary blob
  2832. BOOL * pfInheritanceOverride : NULL or forces inheritance on/off
  2833. LPCTSTR lpszMDPath : Optional path off the open key
  2834. DWORD * pdwAttributes : Optionally returns attributes
  2835. Return Value:
  2836. HRESULT
  2837. --*/
  2838. {
  2839. //
  2840. // Get GetData allocate the buffer for us
  2841. //
  2842. DWORD dwSize = 0;
  2843. DWORD dwDataType = BINARY_METADATA;
  2844. LPBYTE pbData = NULL;
  2845. HRESULT hr = GetPropertyValue(
  2846. dwID,
  2847. dwSize,
  2848. (void *&)pbData,
  2849. &dwDataType,
  2850. pfInheritanceOverride,
  2851. lpszMDPath,
  2852. pdwAttributes
  2853. );
  2854. if (SUCCEEDED(hr))
  2855. {
  2856. //
  2857. // Blob takes ownership of the data, so don't free it...
  2858. //
  2859. ASSERT_READ_PTR2(pbData, dwSize);
  2860. blValue.SetValue(dwSize, pbData, FALSE);
  2861. }
  2862. return hr;
  2863. }
  2864. HRESULT
  2865. CMetaKey::SetValue(
  2866. IN DWORD dwID,
  2867. IN CStrPassword & strlValue,
  2868. IN BOOL * pfInheritanceOverride, OPTIONAL
  2869. IN LPCTSTR lpszMDPath OPTIONAL
  2870. )
  2871. {
  2872. LPTSTR lpstr = NULL;
  2873. HRESULT hr = E_FAIL;
  2874. lpstr = strlValue.GetClearTextPassword();
  2875. if (lpstr)
  2876. {
  2877. hr = SetPropertyValue(
  2878. dwID,
  2879. strlValue.GetByteLength(),
  2880. (void *)lpstr,
  2881. pfInheritanceOverride,
  2882. lpszMDPath
  2883. );
  2884. strlValue.DestroyClearTextPassword(lpstr);
  2885. }
  2886. return hr;
  2887. }
  2888. HRESULT
  2889. CMetaKey::SetValue(
  2890. IN DWORD dwID,
  2891. IN CStringListEx & strlValue,
  2892. IN BOOL * pfInheritanceOverride, OPTIONAL
  2893. IN LPCTSTR lpszMDPath OPTIONAL
  2894. )
  2895. /*++
  2896. Routine Description:
  2897. Store data as string
  2898. Arguments:
  2899. DWORD dwID : Property ID
  2900. CStringListEx & strlValue : Value to be written
  2901. BOOL * pfInheritanceOverride : NULL or forces inheritance on/off
  2902. LPCTSTR lpszMDPath : Optional path (or NULL or "")
  2903. Return Value:
  2904. HRESULT
  2905. --*/
  2906. {
  2907. DWORD cCharacters;
  2908. LPTSTR lpstr = NULL;
  2909. //
  2910. // Flatten value
  2911. //
  2912. strlValue.ConvertToDoubleNullList(cCharacters, lpstr);
  2913. HRESULT hr = SetPropertyValue(
  2914. dwID,
  2915. cCharacters * sizeof(TCHAR),
  2916. (void *)lpstr,
  2917. pfInheritanceOverride,
  2918. lpszMDPath
  2919. );
  2920. delete [] lpstr;
  2921. return hr;
  2922. }
  2923. HRESULT
  2924. CMetaKey::SetValue(
  2925. IN DWORD dwID,
  2926. IN CBlob & blValue,
  2927. IN BOOL * pfInheritanceOverride, OPTIONAL
  2928. IN LPCTSTR lpszMDPath OPTIONAL
  2929. )
  2930. /*++
  2931. Routine Description:
  2932. Store data as binary
  2933. Arguments:
  2934. DWORD dwID : Property ID
  2935. CBlob & blValue : Value to be written
  2936. BOOL * pfInheritanceOverride : NULL or forces inheritance on/off
  2937. LPCTSTR lpszMDPath : Optional path (or NULL or "")
  2938. Return Value:
  2939. HRESULT
  2940. --*/
  2941. {
  2942. return SetPropertyValue(
  2943. dwID,
  2944. blValue.GetSize(),
  2945. (void *)blValue.GetData(),
  2946. pfInheritanceOverride,
  2947. lpszMDPath
  2948. );
  2949. }
  2950. HRESULT
  2951. CMetaKey::DeleteValue(
  2952. DWORD dwID,
  2953. LPCTSTR lpszMDPath OPTIONAL
  2954. )
  2955. /*++
  2956. Routine Description:
  2957. Delete data
  2958. Arguments:
  2959. DWORD dwID : Property ID of property to be deleted
  2960. LPCTSTR lpszMDPath : Optional path (or NULL or "")
  2961. Return Value:
  2962. HRESULT
  2963. --*/
  2964. {
  2965. ASSURE_PROPER_INTERFACE();
  2966. ASSURE_OPEN_KEY();
  2967. METADATA_RECORD mdRecord;
  2968. FETCH_PROPERTY_DATA_OR_FAIL(dwID, mdRecord);
  2969. return DeleteData(
  2970. m_hKey,
  2971. lpszMDPath,
  2972. mdRecord.dwMDIdentifier,
  2973. mdRecord.dwMDDataType
  2974. );
  2975. }
  2976. HRESULT
  2977. CMetaKey::DoesPathExist(
  2978. IN LPCTSTR lpszMDPath
  2979. )
  2980. /*++
  2981. Routine Description:
  2982. Determine if the path exists
  2983. Arguments:
  2984. LPCTSTR lpszMDPath : Relative path off the open key
  2985. Return Value:
  2986. HRESULT, or S_OK if the path exists.
  2987. --*/
  2988. {
  2989. ASSURE_PROPER_INTERFACE();
  2990. ASSURE_OPEN_KEY();
  2991. FILETIME ft;
  2992. return GetLastChangeTime(m_hKey, lpszMDPath, &ft, FALSE);
  2993. }
  2994. HRESULT
  2995. CMetaInterface::Regenerate()
  2996. /*++
  2997. Routine Description:
  2998. Attempt to recreate the interface pointer. This assumes that the interface
  2999. had been successfully created before, but has become invalid at some
  3000. point afterwards.
  3001. Arguments:
  3002. None
  3003. Return Value:
  3004. HRESULT
  3005. --*/
  3006. {
  3007. ASSERT_PTR(m_pInterface); // Must have been initialised
  3008. SAFE_RELEASE(m_pInterface);
  3009. m_hrInterface = Create();
  3010. return m_hrInterface;
  3011. }
  3012. #define GET_TO_INTERFACE2()\
  3013. IMSAdminBase2 * pInterface2 = NULL;\
  3014. HRESULT hr = GetAdminInterface2(&pInterface2);\
  3015. if (SUCCEEDED(hr)) {
  3016. #define RELEASE_AND_RETURN2()\
  3017. if (pInterface2 != NULL)\
  3018. pInterface2->Release();\
  3019. }\
  3020. return hr\
  3021. HRESULT
  3022. CMetaInterface::GetAdminInterface2(IMSAdminBase2 ** pp)
  3023. {
  3024. HRESULT hr = S_OK;
  3025. IMSAdminBase2 * p = NULL;
  3026. if (pp == NULL)
  3027. return E_POINTER;
  3028. if (m_auth.UsesImpersonation())
  3029. {
  3030. IUnknown * punk = NULL;
  3031. hr = m_pInterface->QueryInterface(__uuidof(IUnknown), (void **)&punk);
  3032. if (SUCCEEDED(hr))
  3033. {
  3034. if (SUCCEEDED(hr = m_auth.ApplyProxyBlanket(punk)))
  3035. {
  3036. if (SUCCEEDED(hr = punk->QueryInterface(IID_IMSAdminBase2, (void **)&p)))
  3037. {
  3038. if (p != NULL)
  3039. {
  3040. hr = m_auth.ApplyProxyBlanket(p);
  3041. if (SUCCEEDED(hr))
  3042. {
  3043. *pp = p;
  3044. }
  3045. }
  3046. }
  3047. }
  3048. }
  3049. if (punk != NULL)
  3050. punk->Release();
  3051. }
  3052. else
  3053. {
  3054. hr = m_pInterface->QueryInterface(IID_IMSAdminBase2, (void **)pp);
  3055. }
  3056. return hr;
  3057. }
  3058. //
  3059. // CWamInterface class
  3060. //
  3061. // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  3062. CWamInterface::CWamInterface(
  3063. IN CComAuthInfo * pAuthInfo OPTIONAL
  3064. )
  3065. /*++
  3066. Routine Description:
  3067. Construct and initialize the interface.
  3068. Arguments:
  3069. CComAuthInfo * pAuthInfo : Auth info. NULL indicates the local computer.
  3070. Return Value:
  3071. N/A
  3072. --*/
  3073. : CIISInterface(pAuthInfo),
  3074. m_pInterface(NULL),
  3075. m_fSupportsPooledProc(FALSE)
  3076. {
  3077. //
  3078. // Initialize the interface
  3079. //
  3080. m_hrInterface = Create();
  3081. }
  3082. CWamInterface::CWamInterface(
  3083. IN CWamInterface * pInterface
  3084. )
  3085. /*++
  3086. Routine Description:
  3087. Construct from existing interface (copy constructor)
  3088. Arguments:
  3089. CWamInterface * pInterface : Existing interface
  3090. Return Value:
  3091. N/A
  3092. --*/
  3093. : CIISInterface(&pInterface->m_auth, pInterface->m_hrInterface),
  3094. m_pInterface(pInterface->m_pInterface),
  3095. m_fSupportsPooledProc(FALSE)
  3096. {
  3097. ASSERT_PTR(m_pInterface);
  3098. m_pInterface->AddRef();
  3099. }
  3100. CWamInterface::~CWamInterface()
  3101. /*++
  3102. Routine Description:
  3103. Destructor -- releases the interface.
  3104. Arguments:
  3105. N/A
  3106. Return Value:
  3107. N/A
  3108. --*/
  3109. {
  3110. SAFE_RELEASE(m_pInterface);
  3111. }
  3112. /* protected */
  3113. HRESULT
  3114. CWamInterface::Create()
  3115. /*++
  3116. Routine Description:
  3117. Create the interface with DCOM
  3118. Arguments:
  3119. None
  3120. Return Value:
  3121. HRESULT
  3122. Notes:
  3123. First, it will attempt to create the new interface, if it
  3124. fails, it will attempt to create the downlevel interface
  3125. --*/
  3126. {
  3127. CLSID rgCLSID[2];
  3128. IID rgIID[2];
  3129. rgCLSID[1] = rgCLSID[0] = CLSID_WamAdmin;
  3130. rgIID[0] = IID_IWamAdmin2;
  3131. rgIID[1] = IID_IWamAdmin;
  3132. ASSERT(ARRAY_SIZE(rgCLSID) == ARRAY_SIZE(rgIID));
  3133. int cInterfaces = ARRAY_SIZE(rgCLSID);
  3134. int iInterface;
  3135. HRESULT hr = CIISInterface::Create(
  3136. cInterfaces,
  3137. rgIID,
  3138. rgCLSID,
  3139. &iInterface,
  3140. (IUnknown **)&m_pInterface
  3141. );
  3142. if (SUCCEEDED(hr))
  3143. {
  3144. //
  3145. // Only supported on IWamAdmin2
  3146. //
  3147. m_fSupportsPooledProc = (rgIID[iInterface] == IID_IWamAdmin2);
  3148. }
  3149. return hr;
  3150. }
  3151. HRESULT
  3152. CWamInterface::AppCreate(
  3153. IN LPCTSTR szMDPath,
  3154. IN DWORD dwAppProtection
  3155. )
  3156. /*++
  3157. Routine Description:
  3158. Create application
  3159. Arguments:
  3160. LPCTSTR szMDPath : Metabase path
  3161. DWORD dwAppProtection : APP_INPROC to create in-proc app
  3162. APP_OUTOFPROC to create out-of-proc app
  3163. APP_POOLEDPROC to create a pooled-proc app
  3164. Return Value:
  3165. HRESULT (ERROR_INVALID_PARAMETER if unsupported protection state is requested)
  3166. --*/
  3167. {
  3168. if (m_fSupportsPooledProc)
  3169. {
  3170. //
  3171. // Interface pointer is really IWamAdmin2, so call the new method
  3172. //
  3173. return ((IWamAdmin2 *)m_pInterface)->AppCreate2(szMDPath, dwAppProtection);
  3174. }
  3175. //
  3176. // Call the downlevel API
  3177. //
  3178. if (dwAppProtection == APP_INPROC || dwAppProtection == APP_OUTOFPROC)
  3179. {
  3180. BOOL fInProc = (dwAppProtection == APP_INPROC);
  3181. ASSERT_PTR(m_pInterface);
  3182. return m_pInterface->AppCreate(szMDPath, fInProc);
  3183. }
  3184. return CError(ERROR_INVALID_PARAMETER);
  3185. }
  3186. //
  3187. // CMetaback Class
  3188. //
  3189. // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  3190. const LPCTSTR CMetaBack::s_szMasterAppRoot =\
  3191. SZ_MBN_SEP_STR SZ_MBN_MACHINE SZ_MBN_SEP_STR SZ_MBN_WEB;
  3192. CMetaBack::CMetaBack(
  3193. IN CComAuthInfo * pAuthInfo OPTIONAL
  3194. )
  3195. /*++
  3196. Routine Description:
  3197. Constructor for metabase backup/restore operations class. This object
  3198. is both a WAM interface and a METABASE interface.
  3199. Arguments:
  3200. CComAuthInfo * pAuthInfo : Auth info. NULL indicates the local computer.
  3201. Return Value:
  3202. N/A
  3203. --*/
  3204. : m_dwIndex(0),
  3205. CMetaInterface(pAuthInfo),
  3206. CWamInterface(pAuthInfo)
  3207. {
  3208. }
  3209. /* virtual */
  3210. BOOL
  3211. CMetaBack::Succeeded() const
  3212. /*++
  3213. Routine Description:
  3214. Determine if object was constructed successfully.
  3215. Arguments:
  3216. None
  3217. Return Value:
  3218. TRUE for success, FALSE for failure
  3219. --*/
  3220. {
  3221. return CMetaInterface::Succeeded() && CWamInterface::Succeeded();
  3222. }
  3223. /* virtual */
  3224. HRESULT
  3225. CMetaBack::QueryResult() const
  3226. /*++
  3227. Routine Description:
  3228. Return the construction error for this object
  3229. Arguments:
  3230. None
  3231. Return Value:
  3232. HRESULT from construction errors
  3233. --*/
  3234. {
  3235. //
  3236. // Both interfaces must have constructed successfully
  3237. //
  3238. HRESULT hr = CMetaInterface::QueryResult();
  3239. if (SUCCEEDED(hr))
  3240. {
  3241. hr = CWamInterface::QueryResult();
  3242. }
  3243. return hr;
  3244. }
  3245. HRESULT
  3246. CMetaBack::Restore(
  3247. IN LPCTSTR lpszLocation,
  3248. IN DWORD dwVersion
  3249. )
  3250. /*++
  3251. Routine Description:
  3252. Restore metabase
  3253. Arguments:
  3254. DWORD dwVersion : Backup version
  3255. LPCTSTR lpszLocation : Backup location
  3256. Return Value:
  3257. HRESULT
  3258. --*/
  3259. {
  3260. //
  3261. // Backup and restore the application information from a restore
  3262. //
  3263. CString strPath(s_szMasterAppRoot);
  3264. HRESULT hr = AppDeleteRecoverable(strPath, TRUE);
  3265. if (SUCCEEDED(hr))
  3266. {
  3267. hr = CMetaInterface::Restore(lpszLocation, dwVersion, 0);
  3268. if (SUCCEEDED(hr))
  3269. {
  3270. hr = AppRecover(strPath, TRUE);
  3271. }
  3272. }
  3273. return hr;
  3274. }
  3275. //
  3276. // CIISSvcControl class
  3277. //
  3278. // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  3279. CIISSvcControl::CIISSvcControl(
  3280. IN CComAuthInfo * pAuthInfo OPTIONAL
  3281. )
  3282. /*++
  3283. Routine Description:
  3284. Construct and initialize the interface.
  3285. Arguments:
  3286. CComAuthInfo * pAuthInfo : Auth info. NULL indicates the local computer.
  3287. Return Value:
  3288. N/A
  3289. --*/
  3290. : CIISInterface(pAuthInfo),
  3291. m_pInterface(NULL)
  3292. {
  3293. //
  3294. // Initialize the interface
  3295. //
  3296. m_hrInterface = Create();
  3297. }
  3298. CIISSvcControl::CIISSvcControl(
  3299. IN CIISSvcControl * pInterface
  3300. )
  3301. /*++
  3302. Routine Description:
  3303. Construct from existing interface (copy constructor)
  3304. Arguments:
  3305. CIISSvcControl * pInterface : Existing interface
  3306. Return Value:
  3307. N/A
  3308. --*/
  3309. : CIISInterface(&pInterface->m_auth, pInterface->m_hrInterface),
  3310. m_pInterface(pInterface->m_pInterface)
  3311. {
  3312. ASSERT_PTR(m_pInterface);
  3313. m_pInterface->AddRef();
  3314. }
  3315. CIISSvcControl::~CIISSvcControl()
  3316. /*++
  3317. Routine Description:
  3318. Destructor -- releases the interface.
  3319. Arguments:
  3320. N/A
  3321. Return Value:
  3322. N/A
  3323. --*/
  3324. {
  3325. SAFE_RELEASE(m_pInterface);
  3326. }
  3327. #ifdef KEVLAR
  3328. //
  3329. // CWebCluster class
  3330. //
  3331. // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  3332. CWebCluster::CWebCluster(
  3333. IN CComAuthInfo * pAuthInfo OPTIONAL
  3334. )
  3335. /*++
  3336. Routine Description:
  3337. Construct and initialize the interface.
  3338. Arguments:
  3339. CComAuthInfo * pAuthInfo : Authentication information.
  3340. NULL indicates the local computer
  3341. Return Value:
  3342. N/A
  3343. --*/
  3344. : CIISInterface(pAuthInfo),
  3345. m_pInterface(NULL)
  3346. {
  3347. //
  3348. // Initialize the interface
  3349. //
  3350. m_hrInterface = Create();
  3351. }
  3352. /* virtual */
  3353. CWebCluster::~CWebCluster()
  3354. /*++
  3355. Routine Description:
  3356. Destructor -- releases the interface.
  3357. Arguments:
  3358. N/A
  3359. Return Value:
  3360. N/A
  3361. --*/
  3362. {
  3363. SAFE_RELEASE(m_pInterface);
  3364. }
  3365. #endif // KEVLAR
  3366. //
  3367. // CMetaEnumerator Clas
  3368. //
  3369. // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  3370. CMetaEnumerator::CMetaEnumerator(
  3371. IN CComAuthInfo * pAuthInfo OPTIONAL,
  3372. IN LPCTSTR lpszMDPath OPTIONAL,
  3373. IN METADATA_HANDLE hkBase OPTIONAL
  3374. )
  3375. /*++
  3376. Routine Description:
  3377. Metabase enumerator constructor. This constructor creates a new interface
  3378. and opens a key.
  3379. Arguments:
  3380. CComAuthInfo * pAuthInfo : Auth info. NULL indicates the local computer.
  3381. LPCTSTR lpszMDPath : Metabase path
  3382. METADATA_HANDLE hkBase : Metabase handle
  3383. Return Value:
  3384. N/A
  3385. --*/
  3386. : CMetaKey(pAuthInfo, lpszMDPath, METADATA_PERMISSION_READ, hkBase),
  3387. m_dwIndex(0L)
  3388. {
  3389. }
  3390. CMetaEnumerator::CMetaEnumerator(
  3391. IN CMetaInterface * pInterface,
  3392. IN LPCTSTR lpszMDPath, OPTIONAL
  3393. IN METADATA_HANDLE hkBase OPTIONAL
  3394. )
  3395. /*++
  3396. Routine Description:
  3397. Metabase enumerator constructor. This constructor uses an existing
  3398. interface and opens a key.
  3399. Arguments:
  3400. CMetaInterface * pInterface : Existing interface
  3401. LPCTSTR lpszMDPath : Metabase path
  3402. METADATA_HANDLE hkBase : Metabase handle
  3403. Return Value:
  3404. N/A
  3405. --*/
  3406. : CMetaKey(pInterface, lpszMDPath, METADATA_PERMISSION_READ, hkBase),
  3407. m_dwIndex(0L)
  3408. {
  3409. }
  3410. CMetaEnumerator::CMetaEnumerator(
  3411. IN BOOL fOwnKey,
  3412. IN CMetaKey * pKey
  3413. )
  3414. /*++
  3415. Routine Description:
  3416. Metabase enumerator constructor. This constructor uses an existing
  3417. interface and open key.
  3418. Arguments:
  3419. BOOL fOwnKey : TRUE if we own the key (destructor will close)
  3420. CMetaKey * pKey : Open key
  3421. Return Value:
  3422. N/A
  3423. --*/
  3424. : CMetaKey(fOwnKey, pKey),
  3425. m_dwIndex(0L)
  3426. {
  3427. }
  3428. HRESULT
  3429. CMetaEnumerator::Next(
  3430. OUT CString & strKey,
  3431. IN LPCTSTR lpszMDPath OPTIONAL
  3432. )
  3433. /*++
  3434. Routine Description:
  3435. Get the next subkey
  3436. Arguments:
  3437. CString & str Returns keyname
  3438. LPCTSTR lpszMDPath Optional subpath
  3439. Return Value:
  3440. HRESULT
  3441. --*/
  3442. {
  3443. ASSURE_PROPER_INTERFACE();
  3444. ASSURE_OPEN_KEY();
  3445. TCHAR buf[MAX_PATH];
  3446. HRESULT hr = EnumKeys(m_hKey, lpszMDPath, buf, m_dwIndex++);
  3447. if (SUCCEEDED(hr))
  3448. strKey = buf;
  3449. return hr;
  3450. }
  3451. HRESULT
  3452. CMetaEnumerator::Next(
  3453. OUT DWORD & dwKey,
  3454. OUT CString & strKey,
  3455. IN LPCTSTR lpszMDPath OPTIONAL
  3456. )
  3457. /*++
  3458. Routine Description:
  3459. Get the next subkey as a DWORD. This skips non-numeric
  3460. keynames (including 0) until the first numeric key name
  3461. Arguments:
  3462. DWORD & dwKey Numeric key
  3463. CString & strKey Same key in string format
  3464. LPCTSTR lpszMDPath Optional subpath
  3465. Return Value:
  3466. HRESULT
  3467. --*/
  3468. {
  3469. ASSURE_PROPER_INTERFACE();
  3470. ASSURE_OPEN_KEY();
  3471. HRESULT hr;
  3472. TCHAR buf[MAX_PATH];
  3473. while (TRUE)
  3474. {
  3475. if (SUCCEEDED(hr = EnumKeys(m_hKey, lpszMDPath, buf, m_dwIndex++)))
  3476. {
  3477. if (0 != (dwKey = _ttoi(buf)))
  3478. {
  3479. strKey = buf;
  3480. break;
  3481. }
  3482. }
  3483. else
  3484. break;
  3485. }
  3486. return hr;
  3487. }
  3488. // This method moved from inline to remove dependency on IIDs and CLSIDs
  3489. HRESULT
  3490. CIISSvcControl::Create()
  3491. {
  3492. return CIISInterface::Create(
  3493. 1,
  3494. &IID_IIisServiceControl,
  3495. &CLSID_IisServiceControl,
  3496. NULL,
  3497. (IUnknown **)&m_pInterface
  3498. );
  3499. }
  3500. //
  3501. // CIISApplication class
  3502. //
  3503. // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<</
  3504. CIISApplication::CIISApplication(
  3505. IN CComAuthInfo * pAuthInfo OPTIONAL,
  3506. IN LPCTSTR lpszMetapath
  3507. )
  3508. /*++
  3509. Routine Description:
  3510. Construct IIS application.
  3511. Arguments:
  3512. CComAuthInfo * pAuthInfo : Authentication info. NULL indicates the
  3513. local computer.
  3514. LPCTSTR lpszMetapath : Metabase path
  3515. Return Value:
  3516. N/A
  3517. --*/
  3518. : CWamInterface(pAuthInfo),
  3519. CMetaKey(pAuthInfo),
  3520. m_dwProcessProtection(APP_INPROC),
  3521. m_dwAppState(APPSTATUS_NOTDEFINED),
  3522. m_strFriendlyName(),
  3523. m_strAppRoot(),
  3524. m_strWamPath(lpszMetapath)
  3525. {
  3526. CommonConstruct();
  3527. }
  3528. void
  3529. CIISApplication::CommonConstruct()
  3530. /*++
  3531. Routine Description:
  3532. Perform common construction
  3533. Arguments:
  3534. None
  3535. Return Value:
  3536. None
  3537. --*/
  3538. {
  3539. //
  3540. // Munge the metapath so that WAM doesn't cough up a hairball.
  3541. //
  3542. //
  3543. // BUGBUG: CleanMetaPath() disabled currently
  3544. //
  3545. if (m_strWamPath[0] != SZ_MBN_SEP_CHAR)
  3546. {
  3547. m_strWamPath = SZ_MBN_SEP_CHAR + m_strWamPath;
  3548. }
  3549. do
  3550. {
  3551. m_hrApp = CWamInterface::QueryResult();
  3552. if (FAILED(m_hrApp))
  3553. {
  3554. break;
  3555. }
  3556. m_hrApp = RefreshAppState();
  3557. if (HRESULT_CODE(m_hrApp) == ERROR_PATH_NOT_FOUND)
  3558. {
  3559. //
  3560. // "Path Not Found" errors are acceptable, since
  3561. // the application may not yet exist.
  3562. //
  3563. m_hrApp = S_OK;
  3564. }
  3565. }
  3566. while(FALSE);
  3567. }
  3568. /* virtual */
  3569. BOOL
  3570. CIISApplication::Succeeded() const
  3571. /*++
  3572. Routine Description:
  3573. Determine if object was constructed successfully
  3574. Arguments:
  3575. None
  3576. Return Value:
  3577. TRUE for success, FALSE for failure
  3578. --*/
  3579. {
  3580. return CMetaInterface::Succeeded()
  3581. && CWamInterface::Succeeded()
  3582. && SUCCEEDED(m_hrApp);
  3583. }
  3584. /* virtual */
  3585. HRESULT
  3586. CIISApplication::QueryResult() const
  3587. /*++
  3588. Routine Description:
  3589. Return the construction error for this object
  3590. Arguments:
  3591. None
  3592. Return Value:
  3593. HRESULT from construction errors
  3594. --*/
  3595. {
  3596. //
  3597. // Both interfaces must have constructed successfully
  3598. //
  3599. HRESULT hr = CMetaInterface::QueryResult();
  3600. if (SUCCEEDED(hr))
  3601. {
  3602. hr = CWamInterface::QueryResult();
  3603. if (SUCCEEDED(hr))
  3604. {
  3605. hr = m_hrApp;
  3606. }
  3607. }
  3608. return hr;
  3609. }
  3610. HRESULT
  3611. CIISApplication::RefreshAppState()
  3612. /*++
  3613. Routine Description:
  3614. Refresh the application state
  3615. Arguments:
  3616. None
  3617. Return Value:
  3618. HRESULT
  3619. --*/
  3620. {
  3621. ASSERT(!m_strWamPath.IsEmpty());
  3622. HRESULT hr, hrKeys;
  3623. hr = AppGetStatus(m_strWamPath, &m_dwAppState);
  3624. if (FAILED(hr))
  3625. {
  3626. m_dwAppState = APPSTATUS_NOTDEFINED;
  3627. }
  3628. m_strAppRoot.Empty();
  3629. hrKeys = QueryValue(MD_APP_ROOT, m_strAppRoot, NULL, m_strWamPath);
  3630. m_dwProcessProtection = APP_INPROC;
  3631. hrKeys = QueryValue(
  3632. MD_APP_ISOLATED,
  3633. m_dwProcessProtection,
  3634. NULL,
  3635. m_strWamPath
  3636. );
  3637. m_strFriendlyName.Empty();
  3638. hrKeys = QueryValue(
  3639. MD_APP_FRIENDLY_NAME,
  3640. m_strFriendlyName,
  3641. NULL,
  3642. m_strWamPath
  3643. );
  3644. return hr;
  3645. }
  3646. HRESULT
  3647. CIISApplication::Create(
  3648. IN LPCTSTR lpszName, OPTIONAL
  3649. IN DWORD dwAppProtection
  3650. )
  3651. /*++
  3652. Routine Description:
  3653. Create the application
  3654. Arguments:
  3655. LPCTSTR lpszName : Application name
  3656. DWORD dwAppProtection : APP_INPROC to create in-proc app
  3657. APP_OUTOFPROC to create out-of-proc app
  3658. APP_POOLEDPROC to create a pooled-proc app
  3659. Return Value:
  3660. HRESULT
  3661. --*/
  3662. {
  3663. ASSERT(!m_strWamPath.IsEmpty());
  3664. HRESULT hr = AppCreate(m_strWamPath, dwAppProtection);
  3665. if (SUCCEEDED(hr))
  3666. {
  3667. //
  3668. // Write the friendly app name, which we maintain
  3669. // ourselves. Empty it first, because we might
  3670. // have picked up a name from inheritance.
  3671. //
  3672. m_strFriendlyName.Empty();
  3673. hr = WriteFriendlyName(lpszName);
  3674. RefreshAppState();
  3675. }
  3676. return hr;
  3677. }
  3678. HRESULT
  3679. CIISApplication::WriteFriendlyName(
  3680. IN LPCTSTR lpszName
  3681. )
  3682. /*++
  3683. Routine Description:
  3684. Write the friendly name. This will not write anything
  3685. if the name is the same as it was
  3686. Arguments:
  3687. LPCTSTR lpszName : New friendly name
  3688. Return Value:
  3689. HRESULT
  3690. --*/
  3691. {
  3692. HRESULT hr = S_OK;
  3693. if (m_strFriendlyName.CompareNoCase(lpszName) != 0)
  3694. {
  3695. hr = Open(METADATA_PERMISSION_WRITE, m_strWamPath);
  3696. if (SUCCEEDED(hr))
  3697. {
  3698. ASSERT_PTR(lpszName);
  3699. CString str(lpszName);
  3700. hr = SetValue(MD_APP_FRIENDLY_NAME, str);
  3701. Close();
  3702. if (SUCCEEDED(hr))
  3703. {
  3704. m_strFriendlyName = lpszName;
  3705. }
  3706. }
  3707. }
  3708. return hr;
  3709. }