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

5043 lines
117 KiB

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