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.

1261 lines
31 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name :
  4. metacach.cxx
  5. Abstract:
  6. This module contains the tsunami caching routines for metadata.
  7. Author:
  8. Henry Sanders ( henrysa ) 15-Oct-1996
  9. --*/
  10. #include "TsunamiP.Hxx"
  11. #pragma hdrstop
  12. #include <dbgutil.h>
  13. #include <issched.hxx>
  14. #include <metacach.hxx>
  15. extern TCHAR * FlipSlashes( TCHAR * pszPath );
  16. //
  17. // The number of buckets in our hash table.
  18. //
  19. #define METACACHE_TABLE_SIZE 32
  20. #define METACACHE_ENTRY_SIGN ((DWORD)'ECEM')
  21. #define METACACHE_ENTRY_FREE ((DWORD)'ECEf')
  22. //
  23. // Structure of a metacache table entry.
  24. //
  25. typedef struct _METACACHE_ENTRY {
  26. DWORD Signature;
  27. struct _METACACHE_ENTRY *pNext;
  28. DWORD dwDataSetNumber;
  29. DWORD dwServiceID;
  30. PVOID pMetaData;
  31. DWORD dwRefCount;
  32. PMDFREERTN pFreeRoutine;
  33. BOOL bValid;
  34. } METACACHE_ENTRY, *PMETACACHE_ENTRY;
  35. //
  36. // Structure of a hash table bucket.
  37. //
  38. typedef struct _METACACHE_BUCKET {
  39. PMETACACHE_ENTRY pEntry;
  40. CRITICAL_SECTION csCritSec;
  41. } METACACHE_BUCKET;
  42. METACACHE_BUCKET MetaCacheTable[METACACHE_TABLE_SIZE];
  43. DWORD MetaCacheTimerCookie = 0;
  44. /************************************************************
  45. * Functions
  46. ************************************************************/
  47. dllexp
  48. PVOID
  49. TsFindMetaData(
  50. IN DWORD dwDataSetNumber,
  51. IN DWORD dwServiceID
  52. )
  53. /*++
  54. Routine Description:
  55. This function takes a data set number and service ID, and tries to find
  56. a formatted chunk of metadata in the cache. If it does so, it returns a
  57. pointer to it, otherwise it returns NULL.
  58. Arguments
  59. dwDataSetNumber - The data set number to be found.
  60. dwServiceID - ID of calling service.
  61. --*/
  62. {
  63. DWORD dwIndex;
  64. PMETACACHE_ENTRY pCurrentEntry;
  65. dwIndex = dwDataSetNumber % METACACHE_TABLE_SIZE;
  66. //
  67. // This needes to be protected, we use a critical section per bucket.
  68. //
  69. EnterCriticalSection(&MetaCacheTable[dwIndex].csCritSec);
  70. pCurrentEntry = MetaCacheTable[dwIndex].pEntry;
  71. // Walk the chain on the bucket. If we find a match, return it.
  72. //
  73. while (pCurrentEntry != NULL )
  74. {
  75. PCOMMON_METADATA pCMD;
  76. pCMD = (PCOMMON_METADATA)pCurrentEntry->pMetaData;
  77. pCMD->CheckSignature();
  78. ASSERT(pCMD->QueryCacheInfo() == pCurrentEntry);
  79. if (pCurrentEntry->dwDataSetNumber == dwDataSetNumber &&
  80. pCurrentEntry->dwServiceID == dwServiceID &&
  81. pCurrentEntry->bValid)
  82. {
  83. ASSERT( pCurrentEntry->Signature == METACACHE_ENTRY_SIGN );
  84. // Found a match. Increment the refcount and return a pointer
  85. // to the metadata.
  86. InterlockedIncrement((LONG *)&pCurrentEntry->dwRefCount);
  87. LeaveCriticalSection(&MetaCacheTable[dwIndex].csCritSec);
  88. return pCurrentEntry->pMetaData;
  89. }
  90. // Otherwise try the next one.
  91. pCurrentEntry = pCurrentEntry->pNext;
  92. }
  93. // Didn't find a match, so we'll return NULL.
  94. LeaveCriticalSection(&MetaCacheTable[dwIndex].csCritSec);
  95. return NULL;
  96. }
  97. dllexp
  98. PVOID
  99. TsAddMetaData(
  100. IN PCOMMON_METADATA pMetaData,
  101. IN PMDFREERTN pFreeRoutine,
  102. IN DWORD dwDataSetNumber,
  103. IN DWORD dwServiceID
  104. )
  105. /*++
  106. Routine Description:
  107. Add a chunk of formatted metadata to our cache.
  108. Arguments
  109. pMetaData - MetaData to be added.
  110. dwDataSetNumber - The data set number to be found.
  111. dwServiceID - ID of calling service.
  112. Returns
  113. Pointer to metacache 'handle' to be used when freeing information.
  114. --*/
  115. {
  116. PMETACACHE_ENTRY pNewEntry;
  117. DWORD dwIndex;
  118. pMetaData->CheckSignature();
  119. dwIndex = dwDataSetNumber % METACACHE_TABLE_SIZE;
  120. pNewEntry = (PMETACACHE_ENTRY)ALLOC(sizeof(METACACHE_ENTRY));
  121. if (pNewEntry == NULL)
  122. {
  123. // Couldn't add the entry. No big deal, just return.
  124. return NULL;
  125. }
  126. pNewEntry->Signature = METACACHE_ENTRY_SIGN;
  127. pNewEntry->dwDataSetNumber = dwDataSetNumber;
  128. pNewEntry->dwServiceID = dwServiceID;
  129. pNewEntry->pMetaData = pMetaData;
  130. pNewEntry->pFreeRoutine = pFreeRoutine;
  131. pNewEntry->dwRefCount = 1;
  132. pNewEntry->bValid = TRUE;
  133. pMetaData->SetCacheInfo(pNewEntry);
  134. EnterCriticalSection(&MetaCacheTable[dwIndex].csCritSec);
  135. pNewEntry->pNext = MetaCacheTable[dwIndex].pEntry;
  136. MetaCacheTable[dwIndex].pEntry = pNewEntry;
  137. LeaveCriticalSection(&MetaCacheTable[dwIndex].csCritSec);
  138. return pNewEntry;
  139. }
  140. dllexp
  141. VOID
  142. TsFreeMetaData(
  143. IN PVOID pCacheEntry
  144. )
  145. /*++
  146. Routine Description:
  147. Free a chunk of formatted metadata to the cache. What we really do here
  148. is decrement the ref count. If it goes to 0 and the cache element is
  149. marked deleted, we'll free it here.
  150. Arguments
  151. pMetaData - MetaData to be freed.
  152. --*/
  153. {
  154. PMETACACHE_ENTRY pEntry = (PMETACACHE_ENTRY)pCacheEntry;
  155. PCOMMON_METADATA pCMD;
  156. ASSERT( pEntry->Signature == METACACHE_ENTRY_SIGN );
  157. pCMD = (PCOMMON_METADATA)pEntry->pMetaData;
  158. pCMD->CheckSignature();
  159. ASSERT(pCMD->QueryCacheInfo() == pEntry);
  160. InterlockedDecrement((LONG *)&pEntry->dwRefCount);
  161. }
  162. dllexp
  163. VOID
  164. TsAddRefMetaData(
  165. IN PVOID pCacheEntry
  166. )
  167. /*++
  168. Routine Description:
  169. Increment reference count to chunk of formatted metadata
  170. Arguments
  171. pMetaData - MetaData to be AddRef'ed
  172. --*/
  173. {
  174. PMETACACHE_ENTRY pEntry = (PMETACACHE_ENTRY)pCacheEntry;
  175. ASSERT( pEntry->Signature == METACACHE_ENTRY_SIGN );
  176. InterlockedIncrement((LONG *)&pEntry->dwRefCount);
  177. }
  178. dllexp
  179. VOID
  180. TsFlushMetaCache(
  181. DWORD dwService,
  182. BOOL bTerminating
  183. )
  184. /*++
  185. Routine Description:
  186. Called when we need to flush all of our cached metainformation. We walk
  187. the table, and for each entry we check to see if it's in use. If it's not
  188. we'll free it, otherwise we'll mark it as deleted.
  189. If the passed in dwService ID is non-zero, then we'll only
  190. flush those entries that match the service. Also, if we're terminating,
  191. we'll do some additional checking, and also cancle any callbacks if we need
  192. to.
  193. Arguments
  194. dwService - Service ID of entries to be flushed, 0 for all
  195. services.
  196. bTerminating - TRUE if the caller is terminating.
  197. --*/
  198. {
  199. UINT i;
  200. PMETACACHE_ENTRY pEntry;
  201. PMETACACHE_ENTRY pTrailer;
  202. PCOMMON_METADATA pCMD;
  203. for (i = 0; i < METACACHE_TABLE_SIZE; i++)
  204. {
  205. EnterCriticalSection(&MetaCacheTable[i].csCritSec);
  206. pTrailer = CONTAINING_RECORD(&MetaCacheTable[i].pEntry,
  207. METACACHE_ENTRY, pNext);
  208. // Walk the chain on the bucket. For every entry, if it's not in
  209. // use, free it.
  210. //
  211. while (pTrailer->pNext != NULL )
  212. {
  213. pEntry = pTrailer->pNext;
  214. ASSERT( pEntry->Signature == METACACHE_ENTRY_SIGN );
  215. pCMD = (PCOMMON_METADATA)pEntry->pMetaData;
  216. pCMD->CheckSignature();
  217. ASSERT(pCMD->QueryCacheInfo() == pEntry);
  218. if (dwService == 0 || dwService == pEntry->dwServiceID)
  219. {
  220. if (pEntry->dwRefCount == 0)
  221. {
  222. // This entry is not in use.
  223. // If whoever added it gave us a free routine, call it now.
  224. if (pEntry->pFreeRoutine != NULL)
  225. {
  226. (*(pEntry->pFreeRoutine))(pEntry->pMetaData);
  227. }
  228. // Look at the next one.
  229. pTrailer->pNext = pEntry->pNext;
  230. pEntry->Signature = METACACHE_ENTRY_FREE;
  231. FREE(pEntry);
  232. }
  233. else
  234. {
  235. // In a debug build we'll assert here if we're terminating,
  236. // since that shouldn't happen. In a free build we won't
  237. // assert for that but we will NULL out the free routine to
  238. // keep it from getting called, since presumably the owner is
  239. // going away.
  240. if (bTerminating)
  241. {
  242. DBGPRINTF(( DBG_CONTEXT,
  243. "\n=========================================\n"
  244. "Leftover item in metacache - %8x, bValid = %s\n"
  245. "\t dwServiceID = %8d pMetaData = %8x\n"
  246. "\t dwRefCount = %8d pFreeRoutine = %8x\n"
  247. ,
  248. pEntry,
  249. (pEntry->bValid ? "TRUE" : "FALSE"),
  250. pEntry->dwServiceID,
  251. pEntry->pMetaData,
  252. pEntry->dwRefCount,
  253. pEntry->pFreeRoutine ));
  254. pEntry->pFreeRoutine = NULL;
  255. }
  256. pEntry->bValid = FALSE;
  257. pTrailer = pEntry;
  258. }
  259. }
  260. else
  261. {
  262. pTrailer = pEntry;
  263. }
  264. }
  265. LeaveCriticalSection(&MetaCacheTable[i].csCritSec);
  266. }
  267. }
  268. dllexp
  269. VOID
  270. TsReferenceMetaData(
  271. IN PVOID pEntry
  272. )
  273. /*++
  274. Routine Description:
  275. Called when we need to reference a metadata cache entry. The caller
  276. must have already referenced it once.
  277. Arguments
  278. pEntry - Entry to be referenced.
  279. --*/
  280. {
  281. PMETACACHE_ENTRY pCacheEntry = (PMETACACHE_ENTRY)pEntry;
  282. PCOMMON_METADATA pCMD;
  283. ASSERT( pCacheEntry->Signature == METACACHE_ENTRY_SIGN );
  284. pCMD = (PCOMMON_METADATA)pCacheEntry->pMetaData;
  285. pCMD->CheckSignature();
  286. ASSERT(pCMD->QueryCacheInfo() == pCacheEntry);
  287. InterlockedIncrement((LONG *)&pCacheEntry->dwRefCount);
  288. }
  289. VOID
  290. MetaCacheScavenger(
  291. PVOID pContext
  292. )
  293. /*++
  294. Routine Description:
  295. Called periodically to time out metacache information. We scan the table;
  296. if we find an object that's not in use we free it.
  297. Arguments
  298. None.
  299. --*/
  300. {
  301. UINT i;
  302. PMETACACHE_ENTRY pEntry;
  303. PMETACACHE_ENTRY pTrailer;
  304. PCOMMON_METADATA pCMD;
  305. for (i = 0; i < METACACHE_TABLE_SIZE; i++)
  306. {
  307. if (MetaCacheTable[i].pEntry == NULL)
  308. {
  309. continue;
  310. }
  311. EnterCriticalSection(&MetaCacheTable[i].csCritSec);
  312. pTrailer = CONTAINING_RECORD(&MetaCacheTable[i].pEntry,
  313. METACACHE_ENTRY, pNext);
  314. // Walk the chain on the bucket. For every entry, if it's not in
  315. // use, free it.
  316. //
  317. while (pTrailer->pNext != NULL )
  318. {
  319. pEntry = pTrailer->pNext;
  320. ASSERT( pEntry->Signature == METACACHE_ENTRY_SIGN );
  321. pCMD = (PCOMMON_METADATA)pEntry->pMetaData;
  322. pCMD->CheckSignature();
  323. ASSERT(pCMD->QueryCacheInfo() == pEntry);
  324. if (pEntry->dwRefCount == 0)
  325. {
  326. // This entry is not in use.
  327. // If whoever added it gave us a free routine, call it now.
  328. if (pEntry->pFreeRoutine != NULL)
  329. {
  330. (*(pEntry->pFreeRoutine))(pEntry->pMetaData);
  331. }
  332. // Free the entry and look at the next one.
  333. pTrailer->pNext = pEntry->pNext;
  334. pEntry->Signature = METACACHE_ENTRY_FREE;
  335. FREE(pEntry);
  336. }
  337. else
  338. {
  339. pTrailer = pEntry;
  340. }
  341. }
  342. LeaveCriticalSection(&MetaCacheTable[i].csCritSec);
  343. }
  344. }
  345. dllexp
  346. VOID
  347. _TsValidateMetaCache(
  348. VOID
  349. )
  350. /*++
  351. --*/
  352. {
  353. UINT i;
  354. PMETACACHE_ENTRY pEntry;
  355. PCOMMON_METADATA pCMD;
  356. for (i = 0; i < METACACHE_TABLE_SIZE; i++)
  357. {
  358. if (MetaCacheTable[i].pEntry == NULL)
  359. {
  360. continue;
  361. }
  362. EnterCriticalSection(&MetaCacheTable[i].csCritSec);
  363. pEntry = MetaCacheTable[i].pEntry;
  364. while (pEntry != NULL )
  365. {
  366. ASSERT( pEntry->Signature == METACACHE_ENTRY_SIGN );
  367. pCMD = (PCOMMON_METADATA)pEntry->pMetaData;
  368. pCMD->CheckSignature();
  369. ASSERT(pCMD->QueryCacheInfo() == pEntry);
  370. pEntry = pEntry->pNext;
  371. }
  372. LeaveCriticalSection(&MetaCacheTable[i].csCritSec);
  373. }
  374. }
  375. BOOL
  376. MetaCache_Initialize(
  377. VOID
  378. )
  379. /*++
  380. Routine Description:
  381. Initialize our metacache code.
  382. Arguments
  383. Nothing.
  384. --*/
  385. {
  386. UINT i;
  387. for (i = 0; i < METACACHE_TABLE_SIZE; i++)
  388. {
  389. InitializeCriticalSection(&MetaCacheTable[i].csCritSec);
  390. MetaCacheTable[i].pEntry = NULL;
  391. SET_CRITICAL_SECTION_SPIN_COUNT( &MetaCacheTable[i].csCritSec,
  392. IIS_DEFAULT_CS_SPIN_COUNT);
  393. }
  394. MetaCacheTimerCookie = ScheduleWorkItem(
  395. (PFN_SCHED_CALLBACK) MetaCacheScavenger,
  396. NULL,
  397. 60000, // BUGBUG
  398. TRUE ); // Periodic
  399. if (!MetaCacheTimerCookie)
  400. {
  401. return FALSE;
  402. }
  403. return TRUE;
  404. }
  405. BOOL
  406. MetaCache_Terminate(
  407. VOID
  408. )
  409. /*++
  410. Routine Description:
  411. Terminate our metacache code.
  412. Arguments
  413. Nothing.
  414. --*/
  415. {
  416. if (MetaCacheTimerCookie != 0)
  417. {
  418. RemoveWorkItem(MetaCacheTimerCookie);
  419. MetaCacheTimerCookie = 0;
  420. }
  421. TsFlushMetaCache(0, TRUE);
  422. return TRUE;
  423. }
  424. COMMON_METADATA::COMMON_METADATA(VOID)
  425. : m_IpDnsAccessCheckSize( 0 ),
  426. m_IpDnsAccessCheckPtr ( NULL ),
  427. m_IpDnsAccessCheckTag ( 0 ),
  428. m_fDontLog ( FALSE ),
  429. m_dwAccessPerm ( MD_ACCESS_READ ),
  430. m_dwSslAccessPerm ( 0 ),
  431. m_pAcl ( NULL ),
  432. m_dwAclTag ( 0 ),
  433. m_dwVrLevel ( 0 ),
  434. m_dwVrLen ( 0 ),
  435. m_hVrToken ( NULL ),
  436. m_fVrPassThrough ( FALSE ),
  437. m_dwVrError ( 0 ),
  438. m_Signature ( CMD_SIG )
  439. {
  440. //
  441. // Hmmm, since most of these values aren't getting initialized, if
  442. // somebody went and deleted all the metadata items from the tree, then
  443. // bad things could happen. We should initialize with defaults things
  444. // that might mess us
  445. //
  446. } // COMMON_METADATA::COMMON_METADATA()
  447. COMMON_METADATA::~COMMON_METADATA(VOID)
  448. {
  449. CheckSignature();
  450. if ( m_IpDnsAccessCheckTag )
  451. {
  452. FreeMdTag( m_IpDnsAccessCheckTag );
  453. m_IpDnsAccessCheckTag = 0;
  454. }
  455. if ( m_dwAclTag )
  456. {
  457. FreeMdTag( m_dwAclTag );
  458. m_dwAclTag = 0;
  459. }
  460. if ( m_hVrToken )
  461. {
  462. TsDeleteUserToken( m_hVrToken );
  463. m_hVrToken = NULL;
  464. }
  465. } // COMMON_METADATA::~COMMON_METADATA()
  466. VOID
  467. COMMON_METADATA::FreeMdTag(
  468. DWORD dwTag
  469. )
  470. /*++
  471. Routine Description:
  472. Free a metadata object accessed by reference
  473. Arguments:
  474. dwTag - tag of metadata object reference
  475. Returns:
  476. Nothing
  477. --*/
  478. {
  479. MB mb( (IMDCOM*) m_pInstance->m_Service->QueryMDObject() );
  480. CheckSignature();
  481. mb.ReleaseReferenceData( dwTag );
  482. }
  483. //
  484. // Private constants.
  485. //
  486. #define DEFAULT_MD_RECORDS 40
  487. #define DEFAULT_RECORD_SIZE 50
  488. # define DEF_MD_REC_SIZE ((1 + DEFAULT_MD_RECORDS) * \
  489. (sizeof(METADATA_RECORD) + DEFAULT_RECORD_SIZE))
  490. #define RMD_ASSERT(x) if (!(x)) {DBG_ASSERT(FALSE); return FALSE; }
  491. BOOL
  492. COMMON_METADATA::ReadMetaData(
  493. PIIS_SERVER_INSTANCE pInstance,
  494. MB * pmb,
  495. LPSTR pszURL,
  496. PMETADATA_ERROR_INFO pMDError
  497. )
  498. {
  499. PMETADATA_RECORD pMDRecord;
  500. DWORD dwNumMDRecords;
  501. BYTE tmpBuffer[ DEF_MD_REC_SIZE];
  502. BUFFER TempBuff( tmpBuffer, DEF_MD_REC_SIZE);
  503. DWORD i;
  504. DWORD dwDataSetNumber;
  505. INT ch;
  506. LPSTR pszInVr;
  507. LPSTR pszMinInVr;
  508. DWORD dwNeed;
  509. DWORD dwL;
  510. DWORD dwVRLen;
  511. LPSTR pszVrUserName;
  512. LPSTR pszVrPassword;
  513. BYTE tmpPrivateBuffer[ 20 ];
  514. BUFFER PrivateBuffer( tmpPrivateBuffer, 20 );
  515. DWORD dwPrivateBufferUsed;
  516. CheckSignature();
  517. TsValidateMetaCache();
  518. m_pInstance = pInstance;
  519. DBG_ASSERT( TempBuff.QuerySize() >=
  520. (DEFAULT_MD_RECORDS *
  521. (sizeof(METADATA_RECORD) + DEFAULT_RECORD_SIZE))
  522. );
  523. if ( !pmb->Open( pInstance->QueryMDVRPath() ))
  524. {
  525. return FALSE;
  526. }
  527. if ( !pmb->GetAll( pszURL,
  528. METADATA_INHERIT | METADATA_PARTIAL_PATH | METADATA_REFERENCE,
  529. IIS_MD_UT_FILE,
  530. &TempBuff,
  531. &dwNumMDRecords,
  532. &dwDataSetNumber ))
  533. {
  534. return FALSE;
  535. }
  536. pMDRecord = (PMETADATA_RECORD)TempBuff.QueryPtr();
  537. i = 0;
  538. //
  539. // Check from where we got VR_PATH
  540. //
  541. pszMinInVr = pszURL ;
  542. if ( *pszURL )
  543. {
  544. for ( pszInVr = pszMinInVr + strlen(pszMinInVr) ;; )
  545. {
  546. ch = *pszInVr;
  547. *pszInVr = '\0';
  548. dwNeed = 0;
  549. if ( !pmb->GetString( pszURL, MD_VR_PATH, IIS_MD_UT_FILE, NULL, &dwNeed, 0 ) &&
  550. GetLastError() == ERROR_INSUFFICIENT_BUFFER )
  551. {
  552. *pszInVr = ch;
  553. // VR_PATH was defined at this level !
  554. break;
  555. }
  556. *pszInVr = ch;
  557. if ( ch )
  558. {
  559. if ( pszInVr > pszMinInVr )
  560. {
  561. pszInVr = CharPrev( pszMinInVr, pszInVr );
  562. }
  563. else
  564. {
  565. //
  566. // VR_PATH was defined above Instance vroot
  567. // or not at all. If defined above, then the reference
  568. // path is empty, so we can claim we found it.
  569. // if not defined, then this will be catch later.
  570. //
  571. break;
  572. }
  573. }
  574. // scan for previous delimiter
  575. while ( *pszInVr != '/' && *pszInVr != '\\' )
  576. {
  577. if ( pszInVr > pszMinInVr )
  578. {
  579. pszInVr = CharPrev( pszMinInVr, pszInVr );
  580. }
  581. else
  582. {
  583. //
  584. // VR_PATH was defined above Instance vroot
  585. // or not at all. If defined above, then the reference
  586. // path is empty, so we can claim we found it.
  587. // if not defined, then this will be catch later.
  588. //
  589. break;
  590. }
  591. }
  592. }
  593. dwVRLen = pszInVr - pszMinInVr;
  594. }
  595. else
  596. {
  597. dwVRLen = 0;
  598. pszInVr = pszMinInVr;
  599. }
  600. // Close this now to minimize lock contention.
  601. DBG_REQUIRE(pmb->Close());
  602. for ( dwL = 0 ; pszMinInVr < pszInVr - 1 ; pszMinInVr = CharNext(pszMinInVr) )
  603. {
  604. if ( *pszMinInVr == '/' || *pszMinInVr == '\\' )
  605. {
  606. ++dwL;
  607. }
  608. }
  609. // Now walk through the array of returned metadata objects and format
  610. // each one into our predigested form.
  611. SetVrLevelAndLen( dwL, dwVRLen );
  612. pszVrPassword = NULL;
  613. pszVrUserName = NULL;
  614. dwPrivateBufferUsed = 0;
  615. pMDError->IsValid = FALSE;
  616. for ( ; i < dwNumMDRecords; i++, pMDRecord++ ) {
  617. PVOID pDataPointer;
  618. CHAR *pszMimePtr;
  619. CHAR *pszTemp;
  620. DWORD dwTemp;
  621. pDataPointer = (PVOID) ((PCHAR)TempBuff.QueryPtr() +
  622. (UINT)pMDRecord->pbMDData);
  623. switch ( pMDRecord->dwMDIdentifier ) {
  624. case MD_IP_SEC:
  625. DBG_ASSERT( pMDRecord->dwMDDataTag );
  626. RMD_ASSERT( pMDRecord->dwMDDataType == BINARY_METADATA &&
  627. pMDRecord->dwMDAttributes & METADATA_REFERENCE );
  628. if ( pMDRecord->dwMDDataTag )
  629. {
  630. if ( !SetIpDnsAccessCheck( pMDRecord->pbMDData,
  631. pMDRecord->dwMDDataLen,
  632. pMDRecord->dwMDDataTag ) )
  633. {
  634. goto FreeRefs;
  635. }
  636. }
  637. break;
  638. case MD_ACCESS_PERM:
  639. DBG_ASSERT( pMDRecord->dwMDDataTag == NULL );
  640. RMD_ASSERT( pMDRecord->dwMDDataType == DWORD_METADATA );
  641. SetAccessPerms( *((DWORD *) pDataPointer) );
  642. break;
  643. case MD_SSL_ACCESS_PERM:
  644. DBG_ASSERT( pMDRecord->dwMDDataTag == NULL );
  645. RMD_ASSERT( pMDRecord->dwMDDataType == DWORD_METADATA );
  646. SetSslAccessPerms( *((DWORD *) pDataPointer) );
  647. break;
  648. case MD_DONT_LOG:
  649. DBG_ASSERT( pMDRecord->dwMDDataTag == NULL );
  650. DBG_ASSERT( pMDRecord->dwMDDataType == DWORD_METADATA );
  651. SetDontLogFlag( *((DWORD *) pDataPointer ));
  652. break;
  653. case MD_VR_PATH:
  654. RMD_ASSERT( pMDRecord->dwMDDataType == STRING_METADATA );
  655. if (!QueryVrPath()->Copy((const CHAR *)pDataPointer))
  656. {
  657. goto FreeRefs;
  658. }
  659. break;
  660. case MD_APP_ROOT:
  661. RMD_ASSERT( pMDRecord->dwMDDataType == STRING_METADATA );
  662. if (!QueryAppPath()->Copy((const CHAR *)pDataPointer))
  663. {
  664. goto FreeRefs;
  665. }
  666. break;
  667. case MD_VR_USERNAME:
  668. RMD_ASSERT( pMDRecord->dwMDDataType == STRING_METADATA );
  669. pszVrUserName = (LPSTR)pDataPointer;
  670. break;
  671. case MD_VR_PASSWORD:
  672. RMD_ASSERT( pMDRecord->dwMDDataType == STRING_METADATA );
  673. pszVrPassword = (LPSTR)pDataPointer;
  674. break;
  675. case MD_VR_PASSTHROUGH:
  676. RMD_ASSERT( pMDRecord->dwMDDataType == DWORD_METADATA );
  677. SetVrPassThrough( !!*((DWORD *) pDataPointer) );
  678. break;
  679. case MD_VR_ACL:
  680. DBG_ASSERT( pMDRecord->dwMDDataTag );
  681. RMD_ASSERT( pMDRecord->dwMDDataType == BINARY_METADATA );
  682. if ( pMDRecord->dwMDDataTag )
  683. {
  684. SetAcl( pMDRecord->pbMDData,
  685. pMDRecord->dwMDDataLen,
  686. pMDRecord->dwMDDataTag );
  687. }
  688. break;
  689. default:
  690. if ( !HandlePrivateProperty( pszURL, pInstance, pMDRecord, pDataPointer, &PrivateBuffer, &dwPrivateBufferUsed, pMDError ) )
  691. {
  692. goto FreeRefs;
  693. }
  694. CheckSignature();
  695. break;
  696. }
  697. }
  698. if (!FinishPrivateProperties(&PrivateBuffer, dwPrivateBufferUsed, TRUE))
  699. {
  700. goto FreeRefs;
  701. }
  702. if ( QueryVrPath()->IsEmpty() )
  703. {
  704. DBGPRINTF(( DBG_CONTEXT,
  705. "[ReadMetaData] Virtual Dir Path mapping not found\n" ));
  706. SetLastError( ERROR_FILE_NOT_FOUND );
  707. return FALSE;
  708. }
  709. //
  710. // If this is an UNC share, logon using associated credentials
  711. // keep a reference to this access token in the cache
  712. //
  713. if ( QueryVrPath()->QueryStr()[0] == '\\' &&
  714. QueryVrPath()->QueryStr()[1] == '\\' )
  715. {
  716. if ( pszVrUserName != NULL && pszVrPassword != NULL &&
  717. pszVrUserName[0] )
  718. {
  719. if ( !SetVrUserNameAndPassword( pInstance, pszVrUserName, pszVrPassword ) )
  720. {
  721. return FALSE;
  722. }
  723. }
  724. }
  725. CheckSignature();
  726. TsValidateMetaCache();
  727. return TRUE;
  728. FreeRefs:
  729. FinishPrivateProperties(&PrivateBuffer, dwPrivateBufferUsed, FALSE);
  730. CheckSignature();
  731. TsValidateMetaCache();
  732. for ( ; i < dwNumMDRecords; i++, pMDRecord++ )
  733. {
  734. if ( pMDRecord->dwMDDataTag )
  735. {
  736. pmb->ReleaseReferenceData( pMDRecord->dwMDDataTag );
  737. }
  738. }
  739. return FALSE;
  740. }
  741. BOOL
  742. COMMON_METADATA::SetVrUserNameAndPassword(
  743. PIIS_SERVER_INSTANCE pInstance,
  744. LPSTR pszUserName,
  745. LPSTR pszPassword
  746. )
  747. /*++
  748. Description:
  749. Set the account used to access the virtual root
  750. associated with this metadata
  751. Arguments:
  752. pInstance - current instance
  753. pszUserName - User name
  754. pszPassword - password
  755. Returns:
  756. TRUE if success, otherwise FALSE
  757. --*/
  758. {
  759. LARGE_INTEGER liPwdExpiry;
  760. BOOL fHaveExp;
  761. BOOL fAsGuest;
  762. BOOL fAsAnonymous;
  763. TCP_AUTHENT_INFO TAI;
  764. CheckSignature();
  765. TAI.fDontUseAnonSubAuth = TRUE;
  766. m_hVrToken = TsLogonUser( pszUserName,
  767. pszPassword,
  768. &fAsGuest,
  769. &fAsAnonymous,
  770. pInstance,
  771. &TAI,
  772. NULL,
  773. &liPwdExpiry,
  774. &fHaveExp );
  775. //
  776. // If fail to logo, we remember the error and return SUCCESS
  777. // Caller will have to check metadata after creating it to check
  778. // the error code. Necessary because metadata needs to be set in HTTP_REQUEST
  779. // to send back proper auth status even if virtual root init failed.
  780. //
  781. if ( !m_hVrToken )
  782. {
  783. m_dwVrError = GetLastError();
  784. }
  785. return TRUE;
  786. }
  787. BOOL
  788. COMMON_METADATA::BuildApplPhysicalPath(
  789. STR * pstrApplPhysicalPath
  790. ) const
  791. /*++
  792. Description:
  793. This function builds the physical path for the ApplPath of the current
  794. METADATA object. The ApplPath is a metbase path of the form
  795. /LM/W3Svc/<instance>/app-root-path
  796. This function uses the VR_PATH & portion of the APPL_PATH to
  797. construct the appropriate physical path.
  798. Arguments:
  799. pstrApplPhysicalPath - pointer to STR object that will contain
  800. the physical path on return.
  801. Returns:
  802. TRUE on success and FALSE if there are errors.
  803. Use GetLastError() to get the appropriate error code.
  804. --*/
  805. {
  806. LPCSTR pszInVr;
  807. DWORD dwL;
  808. INT ch;
  809. CheckSignature();
  810. DBG_ASSERT( pstrApplPhysicalPath);
  811. //
  812. // At the minimum copy the current Virtual path
  813. // (1A) NYI: What happens with the default instance for which
  814. // the metabase path is: /LM/W3Svc ??
  815. //
  816. if ( !pstrApplPhysicalPath->Copy( m_strVrPath ) )
  817. {
  818. return FALSE;
  819. }
  820. //
  821. // Scan for the portion of the URL that is part of the VROOT path.
  822. // Do this by scanning forward for all the appropriate # of slashes.
  823. // This works only if the AppRoot is contained within the Vroot
  824. //
  825. // AppPath is of the form: /LM/W3Svc/<instance>/ROOT/app-path
  826. // the VRLevel counts slashes after the <instance> id
  827. // So we scan for the appropriate # of VrLevel "/" + 4
  828. //
  829. // Since the App Path is internal Metabase Path, it should only have
  830. // the '/' and not the weird '\\' :-(
  831. //
  832. pszInVr = m_strAppPath.QueryStr();
  833. DBG_ASSERT( *pszInVr == '/');
  834. dwL = QueryVrLevel() + 4;
  835. while ( dwL-- )
  836. {
  837. if ( *pszInVr )
  838. {
  839. DBG_ASSERT( *pszInVr == '/' );
  840. DBG_ASSERT( *pszInVr != '\\' );
  841. LPCSTR pszNext = strchr( pszInVr + 1, '/');
  842. if ( pszNext == NULL) {
  843. //
  844. // Invalid Metabase Path :( Ignore the error!
  845. // See (1A) above
  846. // SetLastError( ERROR_PATH_NOT_FOUND);
  847. pszInVr = NULL;
  848. dwL = (DWORD ) -1;
  849. break;
  850. }
  851. // set the scanning pointer to next slash.
  852. pszInVr = pszNext;
  853. }
  854. }
  855. DBG_ASSERT( dwL == (DWORD)-1 );
  856. //
  857. // Add a path delimiter char between virtual root mount point
  858. // & significant part of URI
  859. //
  860. DWORD cchAppPath = pstrApplPhysicalPath->QueryCCH();
  861. if ( cchAppPath > 0 )
  862. {
  863. ch = *CharPrev(pstrApplPhysicalPath->QueryStr(), pstrApplPhysicalPath->QueryStr() + cchAppPath);
  864. if ( ch == '/' || ch == '\\')
  865. {
  866. if ( ( pszInVr != NULL ) && *pszInVr )
  867. {
  868. DBG_ASSERT( *pszInVr == '/');
  869. ++pszInVr;
  870. }
  871. } else {
  872. if ( pszInVr == NULL)
  873. {
  874. // happens for the special case (1A)
  875. // Append a "\\" now.
  876. if ( !pstrApplPhysicalPath->Append( "\\")) {
  877. return (FALSE);
  878. }
  879. }
  880. }
  881. }
  882. if ( (pszInVr != NULL) && !pstrApplPhysicalPath->Append( pszInVr ) )
  883. {
  884. return FALSE;
  885. }
  886. //
  887. // insure physical path last char uses standard directory delimiter
  888. //
  889. FlipSlashes( pstrApplPhysicalPath->QueryStr() );
  890. return TRUE;
  891. } // COMMON_METADATA::BuildApplPhysicalPath()
  892. BOOL
  893. COMMON_METADATA::BuildPhysicalPath(
  894. LPSTR pszURL,
  895. STR * pstrPhysicalPath
  896. )
  897. {
  898. LPSTR pszInVr;
  899. DWORD dwL;
  900. INT ch;
  901. CheckSignature();
  902. TsValidateMetaCache();
  903. //
  904. // Build physical path from VR_PATH & portion of URI not used to define VR_PATH
  905. //
  906. //
  907. // skip the URI components used to locate the virtual root
  908. //
  909. pszInVr = pszURL ;
  910. dwL = QueryVrLevel();
  911. while ( dwL-- )
  912. {
  913. if ( *pszInVr )
  914. {
  915. DBG_ASSERT( *pszInVr == '/' || *pszInVr == '\\' );
  916. ++pszInVr;
  917. while ( (ch = *pszInVr) && ch != '/' && ch !='\\' )
  918. {
  919. pszInVr = CharNext( pszInVr );
  920. }
  921. }
  922. }
  923. DBG_ASSERT( dwL == (DWORD)-1 );
  924. if ( !pstrPhysicalPath->Copy( m_strVrPath ) )
  925. {
  926. return FALSE;
  927. }
  928. //
  929. // Add a path delimiter char between virtual root mount point & significant part of URI
  930. //
  931. if ( pstrPhysicalPath->QueryCCH() )
  932. {
  933. ch = *CharPrev(pstrPhysicalPath->QueryStr(), pstrPhysicalPath->QueryStr() +
  934. pstrPhysicalPath->QueryCCH());
  935. if ( (ch == '/' || ch == '\\') && *pszInVr )
  936. {
  937. ++pszInVr;
  938. }
  939. }
  940. if ( !pstrPhysicalPath->Append( pszInVr ) )
  941. {
  942. return FALSE;
  943. }
  944. //
  945. // insure physical path last char uses standard directory delimiter
  946. //
  947. FlipSlashes( pstrPhysicalPath->QueryStr() );
  948. CheckSignature();
  949. TsValidateMetaCache();
  950. return TRUE;
  951. }
  952.