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.

962 lines
23 KiB

  1. /*++
  2. Copyright (c) 1999 Microsoft Corporation
  3. Module Name :
  4. urlinfo.cxx
  5. Abstract:
  6. Gets metadata for URL
  7. Author:
  8. Bilal Alam (balam) 8-Jan-2000
  9. Environment:
  10. Win32 - User Mode
  11. Project:
  12. ULW3.DLL
  13. --*/
  14. #include "precomp.hxx"
  15. #include <stringau.hxx>
  16. ALLOC_CACHE_HANDLER * URL_CONTEXT::sm_pachUrlContexts;
  17. //
  18. // Utility to guard against ~ inconsistency
  19. //
  20. DWORD
  21. CheckIfShortFileName(
  22. IN WCHAR * pszPath,
  23. IN HANDLE hImpersonation,
  24. OUT BOOL * pfShort
  25. );
  26. W3_STATE_URLINFO::W3_STATE_URLINFO()
  27. {
  28. _hr = URL_CONTEXT::Initialize();
  29. }
  30. W3_STATE_URLINFO::~W3_STATE_URLINFO()
  31. {
  32. URL_CONTEXT::Terminate();
  33. }
  34. CONTEXT_STATUS
  35. W3_STATE_URLINFO::OnCompletion(
  36. W3_MAIN_CONTEXT * pMainContext,
  37. DWORD cbCompletion,
  38. DWORD dwCompletionStatus
  39. )
  40. /*++
  41. Routine Description:
  42. Handle URLINFO completions. CheckAccess() is called in DoWork() and this
  43. call is asynchronous.
  44. Arguments:
  45. pMainContext - W3_MAIN_CONTEXT representing execution of state machine
  46. cbCompletion - Number of bytes in an async completion
  47. dwCompletionStatus - Error status of a completion
  48. Return Value:
  49. CONTEXT_STATUS_CONTINUE - if we should continue in state machine
  50. else stop executing the machine and free up the current thread
  51. --*/
  52. {
  53. CONTEXT_STATUS contextStatus;
  54. BOOL fAccessAllowed;
  55. contextStatus = pMainContext->CheckAccess( TRUE, // this is a completion
  56. dwCompletionStatus,
  57. &fAccessAllowed );
  58. if ( contextStatus == CONTEXT_STATUS_PENDING )
  59. {
  60. return CONTEXT_STATUS_PENDING;
  61. }
  62. //
  63. // If access is not allowed, then just finish state machine (
  64. // response has already been sent)
  65. //
  66. if ( !fAccessAllowed )
  67. {
  68. pMainContext->SetFinishedResponse();
  69. }
  70. return CONTEXT_STATUS_CONTINUE;
  71. }
  72. CONTEXT_STATUS
  73. W3_STATE_URLINFO::DoWork(
  74. W3_MAIN_CONTEXT * pMainContext,
  75. DWORD cbCompletion,
  76. DWORD dwCompletionStatus
  77. )
  78. /*++
  79. Routine Description:
  80. Handle retrieving the metadata for this request
  81. Arguments:
  82. pMainContext - W3_MAIN_CONTEXT representing execution of state machine
  83. cbCompletion - Number of bytes in an async completion
  84. dwCompletionStatus - Error status of a completion
  85. Return Value:
  86. CONTEXT_STATUS_CONTINUE - if we should continue in state machine
  87. else stop executing the machine and free up the current thread
  88. --*/
  89. {
  90. URL_CONTEXT * pUrlContext = NULL;
  91. BOOL fFinished = FALSE;
  92. HRESULT hr = NO_ERROR;
  93. W3_METADATA * pMetaData = NULL;
  94. CONTEXT_STATUS contextStatus = CONTEXT_STATUS_CONTINUE;
  95. W3_REQUEST * pHttpRequest = pMainContext->QueryRequest();
  96. W3_RESPONSE * pResponse = pMainContext->QueryResponse();
  97. BOOL fAccessAllowed = FALSE;
  98. DBG_ASSERT( pHttpRequest != NULL );
  99. DBG_ASSERT( pResponse != NULL );
  100. //
  101. // Set the context state
  102. //
  103. hr = URL_CONTEXT::RetrieveUrlContext( pMainContext,
  104. pMainContext->QueryRequest(),
  105. &pUrlContext,
  106. &fFinished );
  107. if ( FAILED( hr ) )
  108. {
  109. goto Failure;
  110. }
  111. DBG_ASSERT( fFinished || ( pUrlContext != NULL ) );
  112. pMainContext->SetUrlContext( pUrlContext );
  113. //
  114. // From now on, errors in this function should not cleanup the URL
  115. // context since it is owned by the main context
  116. //
  117. pUrlContext = NULL;
  118. //
  119. // If filter wants out, leave
  120. //
  121. if ( fFinished )
  122. {
  123. pMainContext->SetDone();
  124. return CONTEXT_STATUS_CONTINUE;
  125. }
  126. //
  127. // Check access now. That means checking for IP/SSL/Certs. We will
  128. // avoid the authentication type check since the others (IP/SSL/Certs)
  129. // take priority.
  130. //
  131. contextStatus = pMainContext->CheckAccess( FALSE, // not a completion
  132. NO_ERROR,
  133. &fAccessAllowed );
  134. if ( contextStatus == CONTEXT_STATUS_PENDING )
  135. {
  136. return CONTEXT_STATUS_PENDING;
  137. }
  138. //
  139. // If we don't have access, then the appropriate error response was
  140. // already sent. Just finish the state machine
  141. //
  142. if ( !fAccessAllowed )
  143. {
  144. pMainContext->SetFinishedResponse();
  145. }
  146. return CONTEXT_STATUS_CONTINUE;
  147. Failure:
  148. if ( pUrlContext != NULL )
  149. {
  150. delete pUrlContext;
  151. }
  152. if ( !pMainContext->QueryResponseSent() )
  153. {
  154. if (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND))
  155. {
  156. // For the non-8dot3 case
  157. pMainContext->QueryResponse()->SetStatus( HttpStatusNotFound );
  158. }
  159. else
  160. {
  161. pMainContext->QueryResponse()->SetStatus( HttpStatusServerError );
  162. }
  163. pMainContext->SetFinishedResponse();
  164. pMainContext->SetErrorStatus( hr );
  165. }
  166. return CONTEXT_STATUS_CONTINUE;
  167. }
  168. //static
  169. HRESULT
  170. URL_CONTEXT::RetrieveUrlContext(
  171. W3_CONTEXT * pW3Context,
  172. W3_REQUEST * pRequest,
  173. OUT URL_CONTEXT ** ppUrlContext,
  174. BOOL * pfFinished
  175. )
  176. /*++
  177. Routine Description:
  178. For a given request, get a URL_CONTEXT which represents the
  179. metadata and URI-specific info for that request
  180. Arguments:
  181. pW3Context - W3_CONTEXT for the request
  182. pRequest - New request to lookup
  183. ppUrlContext - Set to point to new URL_CONTEXT
  184. pfFinished - Set to true if isapi filter said we're finished
  185. Return Value:
  186. HRESULT
  187. --*/
  188. {
  189. STACK_STRU( strUrl, MAX_PATH );
  190. W3_URL_INFO * pUrlInfo = NULL;
  191. W3_METADATA * pMetaData = NULL;
  192. URL_CONTEXT * pUrlContext = NULL;
  193. HRESULT hr = NO_ERROR;
  194. HANDLE hToken = NULL;
  195. if ( pW3Context == NULL ||
  196. pRequest == NULL ||
  197. ppUrlContext == NULL ||
  198. pfFinished == NULL )
  199. {
  200. DBG_ASSERT( FALSE );
  201. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  202. }
  203. *ppUrlContext = NULL;
  204. hr = pRequest->GetUrl( &strUrl );
  205. if ( FAILED( hr ) )
  206. {
  207. goto Failure;
  208. }
  209. //
  210. // Lookup the URI info for this request
  211. //
  212. DBG_ASSERT( g_pW3Server->QueryUrlInfoCache() != NULL );
  213. hr = g_pW3Server->QueryUrlInfoCache()->GetUrlInfo(
  214. pW3Context,
  215. strUrl,
  216. &pUrlInfo );
  217. if ( FAILED( hr ) )
  218. {
  219. goto Failure;
  220. }
  221. //
  222. // Now, create a URL_CONTEXT object which contains the W3_URL_INFO and
  223. // W3_METADATA pointers as well as state information for use on cleanup
  224. //
  225. DBG_ASSERT( pUrlInfo != NULL );
  226. pMetaData = (W3_METADATA*) pUrlInfo->QueryMetaData();
  227. DBG_ASSERT( pMetaData != NULL );
  228. pUrlContext = new URL_CONTEXT( pMetaData, pUrlInfo );
  229. if ( pUrlContext == NULL )
  230. {
  231. hr = HRESULT_FROM_WIN32( ERROR_NOT_ENOUGH_MEMORY );
  232. goto Failure;
  233. }
  234. //
  235. // Now notify URL_MAP filters
  236. //
  237. if ( pW3Context->IsNotificationNeeded( SF_NOTIFY_URL_MAP ) )
  238. {
  239. STACK_STRA( straPhys, MAX_PATH + 1 );
  240. STACK_STRA( straUrl, MAX_PATH + 1 );
  241. BOOL fRet;
  242. HTTP_FILTER_URL_MAP filterMap;
  243. STACK_STRU( strPhysicalPath, MAX_PATH );
  244. hr = straPhys.CopyW( pUrlInfo->QueryPhysicalPath()->QueryStr() );
  245. if ( FAILED( hr ) )
  246. {
  247. goto Failure;
  248. }
  249. hr = straUrl.CopyW( strUrl.QueryStr() );
  250. if ( FAILED( hr ) )
  251. {
  252. goto Failure;
  253. }
  254. filterMap.pszURL = straUrl.QueryStr();
  255. filterMap.pszPhysicalPath = straPhys.QueryStr();
  256. filterMap.cbPathBuff = MAX_PATH + 1;
  257. fRet = pW3Context->NotifyFilters( SF_NOTIFY_URL_MAP,
  258. &filterMap,
  259. pfFinished );
  260. //
  261. // If the filter is done, then we're done
  262. //
  263. if ( *pfFinished )
  264. {
  265. hr = NO_ERROR;
  266. goto Failure;
  267. }
  268. //
  269. // If the physical path was changed, remember it here
  270. //
  271. hr = strPhysicalPath.CopyA( (CHAR*) filterMap.pszPhysicalPath );
  272. if ( FAILED( hr ) )
  273. {
  274. goto Failure;
  275. }
  276. if ( pUrlInfo->QueryPhysicalPath()->QueryCCH() != strPhysicalPath.QueryCCH() ||
  277. wcscmp( pUrlInfo->QueryPhysicalPath()->QueryStr(),
  278. strPhysicalPath.QueryStr() ) != 0 )
  279. {
  280. hr = pUrlContext->SetPhysicalPath( strPhysicalPath );
  281. if ( FAILED( hr ) )
  282. {
  283. goto Failure;
  284. }
  285. }
  286. }
  287. //
  288. // We don't accept short filename since they can break metabase
  289. // equivalency
  290. //
  291. if ( wcschr( pUrlContext->QueryPhysicalPath()->QueryStr(),
  292. L'~' ) )
  293. {
  294. BOOL fShort = FALSE;
  295. if ( pMetaData->QueryVrAccessToken() != NULL )
  296. {
  297. hToken = pMetaData->QueryVrAccessToken()->QueryImpersonationToken();
  298. }
  299. else
  300. {
  301. hToken = NULL;
  302. }
  303. DWORD dwError = CheckIfShortFileName(
  304. pUrlContext->QueryPhysicalPath()->QueryStr(),
  305. hToken,
  306. &fShort );
  307. if ( dwError != ERROR_SUCCESS )
  308. {
  309. hr = HRESULT_FROM_WIN32( dwError );
  310. goto Failure;
  311. }
  312. if ( fShort )
  313. {
  314. hr = HRESULT_FROM_WIN32( ERROR_FILE_NOT_FOUND );
  315. goto Failure;
  316. }
  317. }
  318. *ppUrlContext = pUrlContext;
  319. return S_OK;
  320. Failure:
  321. if ( pUrlContext != NULL )
  322. {
  323. delete pUrlContext;
  324. }
  325. else
  326. {
  327. if ( pUrlInfo != NULL )
  328. {
  329. pUrlInfo->DereferenceCacheEntry();
  330. }
  331. }
  332. return hr;
  333. }
  334. //static
  335. HRESULT
  336. W3_STATE_URLINFO::MapPath(
  337. W3_CONTEXT * pW3Context,
  338. STRU & strUrl,
  339. STRU * pstrPhysicalPath,
  340. DWORD * pcchDirRoot,
  341. DWORD * pcchVRoot,
  342. DWORD * pdwMask
  343. )
  344. /*++
  345. Routine Description:
  346. Send a URL/Physical-Path pair to a filter for processing
  347. Arguments:
  348. pW3Context - W3_CONTEXT for the request
  349. strUrl - The URL to be mapped
  350. pstrPhysicalPath - Filled with the mapped path upon return. Set with
  351. metadata physical path on entry
  352. pcchDirRoot - Set to point to number of characters in found physical path
  353. pcchVRoot - Set to point to number of characters in found virtual path
  354. pdwMask - Set to point to the access perms mask of virtual path
  355. Return Value:
  356. SUCCEEDED()/FAILED()
  357. --*/
  358. {
  359. HRESULT hr = S_OK;
  360. W3_URL_INFO * pUrlInfo = NULL;
  361. W3_METADATA * pMetaData = NULL;
  362. DBG_ASSERT( pstrPhysicalPath );
  363. //
  364. // Get and keep the metadata and urlinfo for this path
  365. //
  366. DBG_ASSERT( g_pW3Server->QueryUrlInfoCache() != NULL );
  367. hr = g_pW3Server->QueryUrlInfoCache()->GetUrlInfo(
  368. pW3Context,
  369. strUrl,
  370. &pUrlInfo );
  371. if ( FAILED( hr ) )
  372. {
  373. goto Exit;
  374. }
  375. DBG_ASSERT( pUrlInfo != NULL );
  376. //
  377. // Call the filters
  378. //
  379. hr = FilterMapPath( pW3Context,
  380. pUrlInfo,
  381. pstrPhysicalPath );
  382. if ( FAILED( hr ) )
  383. {
  384. goto Exit;
  385. }
  386. pMetaData = pUrlInfo->QueryMetaData();
  387. DBG_ASSERT( pMetaData != NULL );
  388. //
  389. // Return the other goodies
  390. //
  391. if ( pcchDirRoot != NULL )
  392. {
  393. *pcchDirRoot = pMetaData->QueryVrPath()->QueryCCH();
  394. }
  395. if ( pcchVRoot != NULL )
  396. {
  397. if (strUrl.QueryCCH())
  398. {
  399. *pcchVRoot = pMetaData->QueryVrLen();
  400. }
  401. else
  402. {
  403. *pcchVRoot = 0;
  404. }
  405. }
  406. if ( pdwMask != NULL )
  407. {
  408. *pdwMask = pMetaData->QueryAccessPerms();
  409. }
  410. Exit:
  411. if ( pUrlInfo != NULL )
  412. {
  413. pUrlInfo->DereferenceCacheEntry();
  414. pUrlInfo = NULL;
  415. }
  416. return hr;
  417. }
  418. // static
  419. HRESULT
  420. W3_STATE_URLINFO::FilterMapPath(
  421. W3_CONTEXT * pW3Context,
  422. W3_URL_INFO * pUrlInfo,
  423. STRU * pstrPhysicalPath
  424. )
  425. /*++
  426. Routine Description:
  427. Have URL_MAP filters do their thing
  428. Arguments:
  429. pW3Context - Context
  430. pUrlInfo - Contains virtual/physical path
  431. pstrPhysicalPath - Filled with physical path
  432. Return Value:
  433. SUCCEEDED()/FAILED()
  434. --*/
  435. {
  436. HRESULT hr = S_OK;
  437. BOOL fFinished = FALSE;
  438. W3_METADATA * pMetaData = NULL;
  439. STACK_STRU( strFilterPath, MAX_PATH );
  440. STRU * pstrFinalPhysical = NULL;
  441. if ( pW3Context == NULL ||
  442. pUrlInfo == NULL ||
  443. pstrPhysicalPath == NULL )
  444. {
  445. DBG_ASSERT( FALSE );
  446. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  447. }
  448. pMetaData = pUrlInfo->QueryMetaData();
  449. DBG_ASSERT( pMetaData != NULL );
  450. //
  451. // We now have the metadata physical path. Let filters change it here
  452. //
  453. if ( pW3Context->IsNotificationNeeded( SF_NOTIFY_URL_MAP ) )
  454. {
  455. STACK_STRA( straPhys, MAX_PATH + 1 );
  456. STACK_STRA( straUrl, MAX_PATH + 1 );
  457. BOOL fRet;
  458. HTTP_FILTER_URL_MAP filterMap;
  459. hr = straPhys.CopyW( pUrlInfo->QueryUrlTranslated()->QueryStr() );
  460. if ( FAILED( hr ) )
  461. {
  462. goto Exit;
  463. }
  464. hr = straUrl.CopyW( pUrlInfo->QueryUrl() );
  465. if ( FAILED( hr ) )
  466. {
  467. goto Exit;
  468. }
  469. filterMap.pszURL = straUrl.QueryStr();
  470. filterMap.pszPhysicalPath = straPhys.QueryStr();
  471. filterMap.cbPathBuff = MAX_PATH + 1;
  472. fRet = pW3Context->NotifyFilters( SF_NOTIFY_URL_MAP,
  473. &filterMap,
  474. &fFinished );
  475. //
  476. // Ignore finished flag in this case since we really can't do much
  477. // to advance to finish (since an ISAPI is calling this)
  478. //
  479. if ( !fRet )
  480. {
  481. hr = HRESULT_FROM_WIN32( GetLastError() );
  482. goto Exit;
  483. }
  484. //
  485. // Remember the mapped path
  486. //
  487. hr = strFilterPath.CopyA( (CHAR*) filterMap.pszPhysicalPath );
  488. if ( FAILED( hr ) )
  489. {
  490. goto Exit;
  491. }
  492. pstrFinalPhysical = &strFilterPath;
  493. }
  494. else
  495. {
  496. //
  497. // No filter is mapping, therefore just take the URL_INFO's physical
  498. // path
  499. //
  500. pstrFinalPhysical = pUrlInfo->QueryUrlTranslated();
  501. DBG_ASSERT( pstrFinalPhysical != NULL );
  502. }
  503. //
  504. // We don't accept short filename since they can break metabase
  505. // equivalency
  506. //
  507. if ( wcschr( pstrFinalPhysical->QueryStr(),
  508. L'~' ) )
  509. {
  510. BOOL fShort = FALSE;
  511. DWORD dwError = CheckIfShortFileName(
  512. pstrFinalPhysical->QueryStr(),
  513. pW3Context->QueryImpersonationToken(),
  514. &fShort );
  515. if ( dwError != ERROR_SUCCESS )
  516. {
  517. hr = HRESULT_FROM_WIN32( dwError );
  518. goto Exit;
  519. }
  520. if ( fShort )
  521. {
  522. hr = HRESULT_FROM_WIN32( ERROR_FILE_NOT_FOUND );
  523. goto Exit;
  524. }
  525. }
  526. //
  527. // Copy the physical path is requested
  528. //
  529. hr = pstrPhysicalPath->Copy( *pstrFinalPhysical );
  530. if ( FAILED( hr ) )
  531. {
  532. goto Exit;
  533. }
  534. Exit:
  535. return hr;
  536. }
  537. DWORD
  538. CheckIfShortFileName(
  539. IN WCHAR * pszPath,
  540. IN HANDLE hImpersonation,
  541. OUT BOOL * pfShort
  542. )
  543. /*++
  544. Description:
  545. This function takes a suspected NT/Win95 short filename and checks if there's
  546. an equivalent long filename. For example, c:\foobar\ABCDEF~1.ABC is the same
  547. as c:\foobar\abcdefghijklmnop.abc.
  548. NOTE: This function should be called unimpersonated - the FindFirstFile() must
  549. be called in the system context since most systems have traverse checking turned
  550. off - except for the UNC case where we must be impersonated to get network access.
  551. Arguments:
  552. pszPath - Path to check
  553. hImpersonation - Impersonation handle if this is a UNC path - can be NULL if not UNC
  554. pfShort - Set to TRUE if an equivalent long filename is found
  555. Returns:
  556. Win32 error on failure
  557. --*/
  558. {
  559. DWORD err = NO_ERROR;
  560. WIN32_FIND_DATA FindData;
  561. WCHAR * psz;
  562. BOOL fUNC;
  563. psz = wcschr( pszPath, L'~' );
  564. *pfShort = FALSE;
  565. fUNC = (*pszPath == L'\\');
  566. //
  567. // Loop for multiple tildas - watch for a # after the tilda
  568. //
  569. while ( psz++ )
  570. {
  571. if ( *psz >= L'0' && *psz <= L'9' )
  572. {
  573. WCHAR achTmp[MAX_PATH];
  574. WCHAR * pchEndSeg;
  575. WCHAR * pchBeginSeg;
  576. HANDLE hFind;
  577. //
  578. // Isolate the path up to the segment with the
  579. // '~' and do the FindFirst with that path
  580. //
  581. pchEndSeg = wcschr( psz, L'\\' );
  582. if ( !pchEndSeg )
  583. {
  584. pchEndSeg = psz + wcslen( psz );
  585. }
  586. //
  587. // If the string is beyond MAX_PATH then we allow it through
  588. //
  589. if ( ((INT) (pchEndSeg - pszPath)) >= MAX_PATH )
  590. {
  591. return NO_ERROR;
  592. }
  593. memcpy( achTmp,
  594. pszPath,
  595. (INT) (pchEndSeg - pszPath) * sizeof( WCHAR ) );
  596. achTmp[pchEndSeg - pszPath] = L'\0';
  597. if ( fUNC && hImpersonation )
  598. {
  599. if ( !SetThreadToken( NULL, hImpersonation ))
  600. {
  601. return GetLastError();
  602. }
  603. }
  604. hFind = FindFirstFileW( achTmp, &FindData );
  605. if ( fUNC && hImpersonation )
  606. {
  607. RevertToSelf();
  608. }
  609. if ( hFind == INVALID_HANDLE_VALUE )
  610. {
  611. err = GetLastError();
  612. DBGPRINTF(( DBG_CONTEXT,
  613. "FindFirst failed!! - \"%s\", error %d\n",
  614. achTmp,
  615. GetLastError() ));
  616. //
  617. // If the FindFirstFile() fails to find the file then return
  618. // success - the path doesn't appear to be a valid path which
  619. // is ok.
  620. //
  621. if ( err == ERROR_FILE_NOT_FOUND ||
  622. err == ERROR_PATH_NOT_FOUND )
  623. {
  624. return NO_ERROR;
  625. }
  626. return err;
  627. }
  628. DBG_REQUIRE( FindClose( hFind ));
  629. //
  630. // Isolate the last segment of the string which should be
  631. // the potential short name equivalency
  632. //
  633. pchBeginSeg = wcsrchr( achTmp, L'\\' );
  634. DBG_ASSERT( pchBeginSeg );
  635. pchBeginSeg++;
  636. //
  637. // If the last segment doesn't match the long name then this is
  638. // the short name version of the path
  639. //
  640. if ( _wcsicmp( FindData.cFileName, pchBeginSeg ))
  641. {
  642. *pfShort = TRUE;
  643. return NO_ERROR;
  644. }
  645. }
  646. psz = wcschr( psz, L'~' );
  647. }
  648. return err;
  649. }
  650. HRESULT
  651. URL_CONTEXT::OpenFile(
  652. FILE_CACHE_USER * pFileUser,
  653. W3_FILE_INFO ** ppOpenFile
  654. )
  655. /*++
  656. Routine Description:
  657. Open the physical path for this request. If a map path filter did some
  658. redirecting, we will use that path. Otherwise we will just use the
  659. path determined by metadata and cached in the W3_URL_INFO
  660. Arguments:
  661. pFileUser - User to open file as
  662. ppOpenFile - Set to file cache entry on success
  663. Return Value:
  664. HRESULT
  665. --*/
  666. {
  667. HRESULT hr;
  668. BOOL fDoCache;
  669. DBG_ASSERT( QueryMetaData() != NULL );
  670. fDoCache = !QueryMetaData()->QueryNoCache();
  671. //
  672. // If an ISAPI filter changed the physical path, then we need to go
  673. // directly to the file cache. Otherwise, we can go thru the
  674. // W3_URL_INFO which may already have the cached file associated
  675. //
  676. if ( _strPhysicalPath.IsEmpty() )
  677. {
  678. //
  679. // No filter. Fast path :-)
  680. //
  681. DBG_ASSERT( _pUrlInfo != NULL );
  682. hr = _pUrlInfo->GetFileInfo( pFileUser,
  683. fDoCache,
  684. ppOpenFile );
  685. }
  686. else
  687. {
  688. //
  689. // Filter case. Must lookup in file cache :-(
  690. //
  691. DBG_ASSERT( g_pW3Server->QueryFileCache() != NULL );
  692. hr = g_pW3Server->QueryFileCache()->GetFileInfo(
  693. _strPhysicalPath,
  694. QueryMetaData()->QueryDirmonConfig(),
  695. pFileUser,
  696. fDoCache,
  697. ppOpenFile );
  698. }
  699. return hr;
  700. }
  701. //static
  702. HRESULT
  703. URL_CONTEXT::Initialize(
  704. VOID
  705. )
  706. /*++
  707. Routine Description:
  708. Initialize URL_CONTEXT lookaside
  709. Arguments:
  710. None
  711. Return Value:
  712. HRESULT
  713. --*/
  714. {
  715. ALLOC_CACHE_CONFIGURATION acConfig;
  716. HRESULT hr = NO_ERROR;
  717. //
  718. // Setup allocation lookaside
  719. //
  720. acConfig.nConcurrency = 1;
  721. acConfig.nThreshold = 100;
  722. acConfig.cbSize = sizeof( URL_CONTEXT );
  723. DBG_ASSERT( sm_pachUrlContexts == NULL );
  724. sm_pachUrlContexts = new ALLOC_CACHE_HANDLER( "URL_CONTEXT",
  725. &acConfig );
  726. if ( sm_pachUrlContexts == NULL )
  727. {
  728. return HRESULT_FROM_WIN32( ERROR_NOT_ENOUGH_MEMORY );
  729. }
  730. return NO_ERROR;
  731. }
  732. //static
  733. VOID
  734. URL_CONTEXT::Terminate(
  735. VOID
  736. )
  737. /*++
  738. Routine Description:
  739. Clean up URL_CONTEXT lookaside
  740. Arguments:
  741. None
  742. Return Value:
  743. HRESULT
  744. --*/
  745. {
  746. if ( sm_pachUrlContexts != NULL )
  747. {
  748. delete sm_pachUrlContexts;
  749. sm_pachUrlContexts = NULL;
  750. }
  751. }