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.

1466 lines
31 KiB

  1. /*++
  2. Copyright (c) 1999-2000 Microsoft Corporation
  3. Module Name:
  4. w3server.cxx
  5. Abstract:
  6. W3_SERVER object holds global state for ULW3.DLL
  7. Author:
  8. Taylor Weiss (TaylorW) 26-Jan-1999
  9. Revision History:
  10. --*/
  11. #include "precomp.hxx"
  12. #include "rawconnection.hxx"
  13. #include "cgi_handler.h"
  14. /*++
  15. class MB_LISTENER
  16. Implements a metabase change listener for W3_SERVER.
  17. --*/
  18. class MB_LISTENER
  19. : public MB_BASE_NOTIFICATION_SINK
  20. {
  21. public:
  22. MB_LISTENER( W3_SERVER * pParent )
  23. : m_pParent( pParent )
  24. {
  25. }
  26. STDMETHOD( SynchronizedSinkNotify )(
  27. DWORD dwMDNumElements,
  28. MD_CHANGE_OBJECT pcoChangeList[]
  29. )
  30. {
  31. return m_pParent->MetabaseChangeNotification( dwMDNumElements, pcoChangeList );
  32. }
  33. private:
  34. W3_SERVER * m_pParent;
  35. };
  36. W3_SERVER::W3_SERVER( BOOL fCompatibilityMode )
  37. : m_Signature (W3_SERVER_SIGNATURE),
  38. m_pMetaBase (NULL),
  39. m_InitStatus (INIT_NONE),
  40. m_fInBackwardCompatibilityMode(fCompatibilityMode),
  41. m_fUseDigestSSP (FALSE),
  42. m_EventLog (L"W3SVC"),
  43. m_pCounterDataBuffer (NULL),
  44. m_dwCounterDataBuffer (0),
  45. m_cSites (0),
  46. m_pTokenCache (NULL),
  47. m_pUlCache (NULL),
  48. m_pUrlInfoCache (NULL),
  49. m_pFileCache (NULL),
  50. m_pMetaCache (NULL)
  51. {
  52. }
  53. W3_SERVER::~W3_SERVER()
  54. {
  55. if (m_pCounterDataBuffer != NULL)
  56. {
  57. LocalFree(m_pCounterDataBuffer);
  58. m_pCounterDataBuffer = NULL;
  59. }
  60. m_Signature = W3_SERVER_FREE_SIGNATURE;
  61. }
  62. // static
  63. DWORD W3_SITE_LIST::ExtractKey(const W3_SITE *site)
  64. {
  65. return site->QueryId();
  66. }
  67. // static
  68. VOID W3_SITE_LIST::AddRefRecord(W3_SITE *site, int nIncr)
  69. {
  70. if (nIncr > 0)
  71. {
  72. site->AddRef();
  73. }
  74. else if (nIncr < 0)
  75. {
  76. site->Release();
  77. }
  78. else
  79. {
  80. DBG_ASSERT( !"Invalid reference");
  81. }
  82. }
  83. HRESULT FakeCollectCounters(PBYTE *ppCounterData,
  84. DWORD *pdwCounterData)
  85. {
  86. return g_pW3Server->CollectCounters(ppCounterData,
  87. pdwCounterData);
  88. }
  89. HRESULT
  90. W3_SERVER::Initialize(
  91. INT argc,
  92. LPWSTR argv[]
  93. )
  94. /*++
  95. Routine Description:
  96. Initialize ULW3.DLL but do not begin listening for requests
  97. Arguments:
  98. argc - Command line argument count
  99. argv[] - Command line arguments (from WAS)
  100. Return Value:
  101. HRESULT
  102. --*/
  103. {
  104. HRESULT hr = NOERROR;
  105. ULATQ_CONFIG ulatqConfig;
  106. INT iRet;
  107. WSADATA wsaData;
  108. DBGPRINTF((
  109. DBG_CONTEXT,
  110. "Initializing the W3 Server Started CTC = %d \n",
  111. GetTickCount()
  112. ));
  113. //
  114. // Keep track of how much we have initialized so that we can cleanup
  115. // only that which is necessary
  116. //
  117. //
  118. // Initialize Computer name, trivial so doesn't need its own state
  119. //
  120. DWORD cbSize = sizeof m_pszComputerName;
  121. if (!GetComputerNameA(m_pszComputerName, &cbSize))
  122. {
  123. strcpy(m_pszComputerName, "<Server>");
  124. }
  125. m_cchComputerName = strlen(m_pszComputerName);
  126. m_InitStatus = INIT_NONE;
  127. //
  128. // Initialize IISUTIL
  129. //
  130. if ( !InitializeIISUtil() )
  131. {
  132. hr = HRESULT_FROM_WIN32( GetLastError() );
  133. DBGPRINTF(( DBG_CONTEXT,
  134. "Error initializing IISUTIL. hr = %x\n",
  135. hr ));
  136. goto exit;
  137. }
  138. m_InitStatus = INIT_IISUTIL;
  139. DBGPRINTF((
  140. DBG_CONTEXT,
  141. "W3 Server initializing WinSock. CTC = %d \n",
  142. GetTickCount()
  143. ));
  144. //
  145. // Initialize WinSock
  146. //
  147. if ( WSAStartup( MAKEWORD( 1, 1 ), &wsaData ) != 0 )
  148. {
  149. hr = HRESULT_FROM_WIN32( WSAGetLastError() );
  150. DBGPRINTF(( DBG_CONTEXT,
  151. "Error initializing WinSock. hr = %x\n",
  152. hr ));
  153. goto exit;
  154. }
  155. m_InitStatus = INIT_WINSOCK;
  156. DBGPRINTF((
  157. DBG_CONTEXT,
  158. "W3 Server WinSock initialized. CTC = %d \n",
  159. GetTickCount()
  160. ));
  161. //
  162. // Initialize the metabase access (ABO)
  163. //
  164. hr = CoCreateInstance( CLSID_MSAdminBase,
  165. NULL,
  166. CLSCTX_SERVER,
  167. IID_IMSAdminBase,
  168. (LPVOID *)&(m_pMetaBase)
  169. );
  170. if( FAILED(hr) )
  171. {
  172. DBGPRINTF(( DBG_CONTEXT,
  173. "Error creating ABO object. hr = %x\n",
  174. hr ));
  175. goto exit;
  176. }
  177. hr = ReadUseDigestSSP();
  178. if( FAILED(hr) )
  179. {
  180. DBGPRINTF(( DBG_CONTEXT,
  181. "Error reading UseDigestSSP property. hr = %x\n",
  182. hr ));
  183. goto exit;
  184. }
  185. m_pMetaBase->GetSystemChangeNumber( &m_dwSystemChangeNumber );
  186. m_InitStatus = INIT_METABASE;
  187. DBGPRINTF((
  188. DBG_CONTEXT,
  189. "W3 Server Metabase initialized. CTC = %d \n",
  190. GetTickCount()
  191. ));
  192. //
  193. // Initialize metabase change notification mechanism
  194. //
  195. m_pMetabaseListener = new MB_LISTENER( this );
  196. if ( m_pMetabaseListener == NULL )
  197. {
  198. hr = HRESULT_FROM_WIN32( ERROR_NOT_ENOUGH_MEMORY );
  199. goto exit;
  200. }
  201. m_InitStatus = INIT_MB_LISTENER;
  202. //
  203. // Initialize global filter list
  204. //
  205. hr = GlobalFilterInitialize();
  206. if ( FAILED( hr ) )
  207. {
  208. DBGPRINTF(( DBG_CONTEXT,
  209. "Error doing global filter initialization. hr = %x\n",
  210. hr ));
  211. goto exit;
  212. }
  213. m_InitStatus = INIT_FILTERS;
  214. //
  215. // Initialize W3_SITE
  216. //
  217. hr = W3_SITE::W3SiteInitialize();
  218. if ( FAILED( hr ) )
  219. {
  220. DBGPRINTF(( DBG_CONTEXT,
  221. "Error doing global W3_SITE initialization. hr = %x\n",
  222. hr ));
  223. goto exit;
  224. }
  225. m_InitStatus = INIT_W3_SITE;
  226. //
  227. // Initialize site list
  228. //
  229. m_pSiteList = new W3_SITE_LIST();
  230. if ( m_pSiteList == NULL )
  231. {
  232. hr = HRESULT_FROM_WIN32( ERROR_NOT_ENOUGH_MEMORY );
  233. goto exit;
  234. }
  235. m_InitStatus = INIT_SITE_LIST;
  236. //
  237. // Initialize ULATQ
  238. //
  239. ulatqConfig.pfnNewRequest = W3_MAIN_CONTEXT::OnNewRequest;
  240. ulatqConfig.pfnIoCompletion = W3_MAIN_CONTEXT::OnIoCompletion;
  241. ulatqConfig.pfnDisconnect = OnUlDisconnect;
  242. ulatqConfig.pfnOnShutdown = W3_SERVER::OnShutdown;
  243. ulatqConfig.pfnCollectCounters = FakeCollectCounters;
  244. hr = UlAtqInitialize( argc,
  245. argv,
  246. &ulatqConfig );
  247. if( FAILED(hr) )
  248. {
  249. DBGPRINTF(( DBG_CONTEXT,
  250. "Error initializing ULATQ. hr = %x\n",
  251. hr ));
  252. goto exit;
  253. }
  254. m_InitStatus = INIT_ULATQ;
  255. DBGPRINTF((
  256. DBG_CONTEXT,
  257. "W3 Server UlAtq initialized (ipm has signalled). CTC = %d \n",
  258. GetTickCount()
  259. ));
  260. //
  261. // Initialize caches
  262. //
  263. hr = InitializeCaches();
  264. if ( FAILED( hr ) )
  265. {
  266. DBGPRINTF(( DBG_CONTEXT,
  267. "Error initializing caches. hr = %x\n",
  268. hr ));
  269. goto exit;
  270. }
  271. m_InitStatus = INIT_CACHES;
  272. //
  273. // Initialize connection table
  274. //
  275. hr = W3_CONNECTION::Initialize();
  276. if ( FAILED( hr ) )
  277. {
  278. DBGPRINTF(( DBG_CONTEXT,
  279. "Error initializing connection table. hr = %x\n",
  280. hr ));
  281. goto exit;
  282. }
  283. m_InitStatus = INIT_W3_CONNECTION;
  284. //
  285. // Initialize W3_CONTEXTs
  286. //
  287. hr = W3_CONTEXT::Initialize();
  288. if ( FAILED( hr ) )
  289. {
  290. DBGPRINTF(( DBG_CONTEXT,
  291. "Error initializing W3_CONTEXT globals. hr = %x\n",
  292. hr ));
  293. goto exit;
  294. }
  295. m_InitStatus = INIT_W3_CONTEXT;
  296. //
  297. // Initialize W3_REQUEST
  298. //
  299. hr = W3_REQUEST::Initialize();
  300. if ( FAILED( hr ) )
  301. {
  302. DBGPRINTF(( DBG_CONTEXT,
  303. "Error initializing W3_REQUEST globals. hr = %x\n",
  304. hr ));
  305. goto exit;
  306. }
  307. m_InitStatus = INIT_W3_REQUEST;
  308. //
  309. // Initialize W3_RESPONSE
  310. //
  311. hr = W3_RESPONSE::Initialize();
  312. if ( FAILED( hr ) )
  313. {
  314. DBGPRINTF(( DBG_CONTEXT,
  315. "Error initializing W3_RESPONSE globals. hr = %x\n",
  316. hr ));
  317. goto exit;
  318. }
  319. m_InitStatus = INIT_W3_RESPONSE;
  320. //
  321. // Initialize server variables
  322. //
  323. hr = SERVER_VARIABLE_HASH::Initialize();
  324. if ( FAILED( hr ) )
  325. {
  326. DBGPRINTF(( DBG_CONTEXT,
  327. "Error initializing server variable hash table. hr = %x\n",
  328. hr ));
  329. goto exit;
  330. }
  331. m_InitStatus = INIT_SERVER_VARIABLES;
  332. //
  333. // Initialize Mime-mappings
  334. //
  335. hr = InitializeMimeMap(INET_INFO_PARAMETERS_KEY);
  336. if ( FAILED( hr ) )
  337. {
  338. DBGPRINTF(( DBG_CONTEXT,
  339. "Error initializing mime map table. hr = %x\n",
  340. hr ));
  341. goto exit;
  342. }
  343. m_InitStatus = INIT_MIME_MAP;
  344. //
  345. // Initialize logging
  346. //
  347. if (FAILED(hr = LOGGING::Initialize()))
  348. {
  349. goto exit;
  350. }
  351. m_InitStatus = INIT_LOGGING;
  352. //
  353. // If we are in backward compatibility mode, then initialize stream
  354. // filter here
  355. //
  356. if (m_fInBackwardCompatibilityMode)
  357. {
  358. hr = RAW_CONNECTION::Initialize();
  359. if ( FAILED( hr ) )
  360. {
  361. DBGPRINTF(( DBG_CONTEXT,
  362. "Error initialize ISAPI raw data filter support. hr = %x\n",
  363. hr ));
  364. goto exit;
  365. }
  366. }
  367. m_InitStatus = INIT_RAW_CONNECTION;
  368. //
  369. // Client certificate object wrapper
  370. //
  371. hr = CERTIFICATE_CONTEXT::Initialize();
  372. if ( FAILED( hr ) )
  373. {
  374. DBGPRINTF(( DBG_CONTEXT,
  375. "Error initializing certificate contexts. hr = %x\n",
  376. hr ));
  377. goto exit;
  378. }
  379. m_InitStatus = INIT_CERTIFICATE_CONTEXT;
  380. //
  381. // Initialize Http Compression
  382. // Ignore failure but remember if we Initialized.
  383. //
  384. hr = HTTP_COMPRESSION::Initialize();
  385. if ( FAILED( hr ) )
  386. {
  387. DBGPRINTF(( DBG_CONTEXT,
  388. "Error initializing Http Compression. hr = %x\n",
  389. hr ));
  390. hr = S_OK;
  391. }
  392. else
  393. {
  394. m_InitStatus = INIT_HTTP_COMPRESSION;
  395. }
  396. exit:
  397. return hr;
  398. }
  399. VOID
  400. W3_SERVER::Terminate(
  401. HRESULT hrReason
  402. )
  403. /*++
  404. Routine Description:
  405. Terminate ULW3 globals. This should be done after we have stopped
  406. listening for new requests (duh)
  407. Arguments:
  408. None
  409. Return Value:
  410. TRUE if successful, else FALSE
  411. --*/
  412. {
  413. DBGPRINTF(( DBG_CONTEXT,
  414. "Terminating W3_SERVER object\n" ));
  415. //
  416. // Wait for all threads doing W3CORE stuff to drain
  417. //
  418. W3_MAIN_CONTEXT::WaitForThreadDrain();
  419. switch( m_InitStatus )
  420. {
  421. case INIT_HTTP_COMPRESSION:
  422. HTTP_COMPRESSION::Terminate();
  423. case INIT_CERTIFICATE_CONTEXT:
  424. CERTIFICATE_CONTEXT::Terminate();
  425. case INIT_RAW_CONNECTION:
  426. if (m_fInBackwardCompatibilityMode)
  427. {
  428. RAW_CONNECTION::Terminate();
  429. }
  430. case INIT_LOGGING:
  431. LOGGING::Terminate();
  432. case INIT_MIME_MAP:
  433. CleanupMimeMap();
  434. case INIT_SERVER_VARIABLES:
  435. SERVER_VARIABLE_HASH::Terminate();
  436. case INIT_W3_RESPONSE:
  437. W3_RESPONSE::Terminate();
  438. case INIT_W3_REQUEST:
  439. W3_REQUEST::Terminate();
  440. case INIT_W3_CONTEXT:
  441. W3_CONTEXT::Terminate();
  442. case INIT_W3_CONNECTION:
  443. W3_CONNECTION::Terminate();
  444. case INIT_CACHES:
  445. TerminateCaches();
  446. case INIT_ULATQ:
  447. UlAtqTerminate( hrReason );
  448. case INIT_SITE_LIST:
  449. delete m_pSiteList;
  450. m_pSiteList = NULL;
  451. case INIT_W3_SITE:
  452. W3_SITE::W3SiteTerminate();
  453. case INIT_FILTERS:
  454. GlobalFilterTerminate();
  455. case INIT_MB_LISTENER:
  456. if ( m_pMetabaseListener != NULL )
  457. {
  458. m_pMetabaseListener->Release();
  459. m_pMetabaseListener = NULL;
  460. }
  461. case INIT_METABASE:
  462. if ( m_pMetaBase )
  463. {
  464. m_pMetaBase->Release();
  465. }
  466. case INIT_WINSOCK:
  467. WSACleanup();
  468. case INIT_IISUTIL:
  469. TerminateIISUtil();
  470. }
  471. m_InitStatus = INIT_NONE;
  472. }
  473. HRESULT
  474. W3_SERVER::LoadString(
  475. DWORD dwStringID,
  476. CHAR * pszString,
  477. DWORD * pcbString
  478. )
  479. /*++
  480. Routine Description:
  481. Load a resource string from W3CORE.DLL
  482. Arguments:
  483. dwStringID - String ID
  484. pszString - Filled with string
  485. pcbString - On input the size of the buffer pszString, on successful
  486. output, the length of the string copied to pszString
  487. Return Value:
  488. HRESULT
  489. --*/
  490. {
  491. DWORD cbCopied;
  492. if ( pszString == NULL ||
  493. pcbString == NULL )
  494. {
  495. DBG_ASSERT( FALSE );
  496. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  497. }
  498. cbCopied = LoadStringA( GetModuleHandleA( "W3CORE.DLL" ),
  499. dwStringID,
  500. pszString,
  501. *pcbString );
  502. if ( cbCopied == 0 )
  503. {
  504. return HRESULT_FROM_WIN32( GetLastError() );
  505. }
  506. *pcbString = cbCopied;
  507. return NO_ERROR;
  508. }
  509. HRESULT
  510. W3_SERVER::StartListen(
  511. VOID
  512. )
  513. /*++
  514. Routine Description:
  515. Begin listening for requests. This function will return once we have
  516. stopped listening for requests (due to WAS stopping us for some reason)
  517. Listen for metabase changes.
  518. Arguments:
  519. None
  520. Return Value:
  521. HRESULT
  522. --*/
  523. {
  524. HRESULT hr = NOERROR;
  525. DBG_ASSERT( m_pMetabaseListener );
  526. //
  527. // Starting getting metabase changes
  528. //
  529. hr = m_pMetabaseListener->StartListening( m_pMetaBase );
  530. if ( FAILED( hr ) )
  531. {
  532. DBGPRINTF(( DBG_CONTEXT,
  533. "Error trying to listen for metabase changes. hr = %x\n",
  534. hr ));
  535. return hr;
  536. }
  537. //
  538. // Listen for the stream filter
  539. //
  540. if (m_fInBackwardCompatibilityMode)
  541. {
  542. hr = RAW_CONNECTION::StartListening();
  543. if ( FAILED( hr ) )
  544. {
  545. DBGPRINTF(( DBG_CONTEXT,
  546. "Error listening on filter channel. hr = %x\n",
  547. hr ));
  548. m_pMetabaseListener->StopListening( m_pMetaBase );
  549. return hr;
  550. }
  551. }
  552. //
  553. // Start listening for requests
  554. //
  555. hr = UlAtqStartListen();
  556. if( FAILED( hr ) )
  557. {
  558. DBGPRINTF(( DBG_CONTEXT,
  559. "Error listening for HTTP requests. hr = %x\n",
  560. hr ));
  561. if (m_fInBackwardCompatibilityMode)
  562. {
  563. RAW_CONNECTION::StopListening();
  564. }
  565. m_pMetabaseListener->StopListening( m_pMetaBase );
  566. return hr;
  567. }
  568. //
  569. // StartListen() will return when we are to shutdown.
  570. //
  571. m_pMetabaseListener->StopListening( m_pMetaBase );
  572. return NO_ERROR;
  573. }
  574. W3_SITE *
  575. W3_SERVER::FindSite(
  576. DWORD dwInstance
  577. )
  578. {
  579. W3_SITE *site = NULL;
  580. LK_RETCODE lkrc = m_pSiteList->FindKey(dwInstance, &site);
  581. if (site != NULL)
  582. {
  583. DBG_ASSERT(lkrc == LK_SUCCESS);
  584. }
  585. return site;
  586. }
  587. BOOL W3_SERVER::AddSite(W3_SITE *site,
  588. bool fOverWrite)
  589. {
  590. if (m_pSiteList->InsertRecord(site, fOverWrite) == LK_SUCCESS)
  591. {
  592. if (!fOverWrite)
  593. {
  594. InterlockedIncrement((LPLONG)&m_cSites);
  595. }
  596. return TRUE;
  597. }
  598. return FALSE;
  599. }
  600. BOOL W3_SERVER::RemoveSite(W3_SITE *pInstance)
  601. {
  602. if (m_pSiteList->DeleteRecord(pInstance) == LK_SUCCESS)
  603. {
  604. InterlockedDecrement((LPLONG)&m_cSites);
  605. return TRUE;
  606. }
  607. return FALSE;
  608. }
  609. void W3_SERVER::DestroyAllSites()
  610. {
  611. m_pSiteList->Clear();
  612. }
  613. HRESULT
  614. W3_SERVER::MetabaseChangeNotification(
  615. DWORD dwMDNumElements,
  616. MD_CHANGE_OBJECT pcoChangeList[]
  617. )
  618. /*++
  619. Routine Description:
  620. This is the entry point for metabase changes.
  621. It just loops through pcoChangeList and passes
  622. the change to the handler method.
  623. Arguments:
  624. dwMDNumElements - Number of change objects
  625. pcoChangeList - Array of change objects
  626. Return Value:
  627. --*/
  628. {
  629. DBGPRINTF(( DBG_CONTEXT,
  630. "MetabaseChangeNotification called.\n"
  631. ));
  632. //
  633. // Verify that the change is for /LM/W3SVC/ or lower
  634. // and dispatch the change.
  635. //
  636. HRESULT hr = NOERROR;
  637. for( DWORD i = 0; i < dwMDNumElements; ++i )
  638. {
  639. if( _wcsnicmp( pcoChangeList[i].pszMDPath,
  640. W3_SERVER_MB_PATH,
  641. W3_SERVER_MB_PATH_CCH ) == 0 )
  642. {
  643. hr = HandleMetabaseChange( pcoChangeList[i] );
  644. }
  645. }
  646. //
  647. // Update system change number for use by file cache (etags)
  648. //
  649. m_pMetaBase->GetSystemChangeNumber( &m_dwSystemChangeNumber );
  650. return hr;
  651. }
  652. VOID
  653. W3_SERVER::TerminateCaches(
  654. VOID
  655. )
  656. /*++
  657. Routine Description:
  658. Cleanup all the caches
  659. Arguments:
  660. None
  661. Return Value:
  662. None
  663. --*/
  664. {
  665. //
  666. // First flush all caches (only references which should remain on cached
  667. // objects should be thru the hash tables themselves). Once we have
  668. // flushed all the caches, all the cached objects should go away.
  669. //
  670. // If they don't that's a bug and ACache assert will fire
  671. //
  672. W3CacheFlushAllCaches();
  673. //
  674. // Now just unregister and cleanup the caches
  675. //
  676. if ( m_pMetaCache != NULL )
  677. {
  678. W3CacheUnregisterCache( m_pMetaCache );
  679. m_pMetaCache->Terminate();
  680. delete m_pMetaCache;
  681. m_pMetaCache = NULL;
  682. }
  683. if ( m_pFileCache != NULL )
  684. {
  685. W3CacheUnregisterCache( m_pFileCache );
  686. m_pFileCache->Terminate();
  687. delete m_pFileCache;
  688. m_pFileCache = NULL;
  689. }
  690. if ( m_pTokenCache != NULL )
  691. {
  692. W3CacheUnregisterCache( m_pTokenCache );
  693. m_pTokenCache->Terminate();
  694. delete m_pTokenCache;
  695. m_pTokenCache = NULL;
  696. }
  697. if ( m_pUrlInfoCache != NULL )
  698. {
  699. W3CacheUnregisterCache( m_pUrlInfoCache );
  700. m_pUrlInfoCache->Terminate();
  701. delete m_pUrlInfoCache;
  702. m_pUrlInfoCache = NULL;
  703. }
  704. if ( m_pUlCache != NULL )
  705. {
  706. W3CacheUnregisterCache( m_pUlCache );
  707. m_pUlCache->Terminate();
  708. delete m_pUlCache;
  709. m_pUlCache = NULL;
  710. }
  711. W3CacheTerminate();
  712. }
  713. HRESULT
  714. W3_SERVER::InitializeCaches(
  715. VOID
  716. )
  717. /*++
  718. Routine Description:
  719. Initialize caches
  720. Arguments:
  721. None
  722. Return Value:
  723. HRESULT
  724. --*/
  725. {
  726. HRESULT hr = NO_ERROR;
  727. BOOL fCacheInit = FALSE;
  728. //
  729. // Url cache
  730. //
  731. m_pUrlInfoCache = new W3_URL_INFO_CACHE;
  732. if ( m_pUrlInfoCache != NULL )
  733. {
  734. hr = m_pUrlInfoCache->Initialize();
  735. if ( FAILED( hr ) )
  736. {
  737. delete m_pUrlInfoCache;
  738. m_pUrlInfoCache = NULL;
  739. }
  740. }
  741. if ( m_pUrlInfoCache == NULL )
  742. {
  743. goto Failure;
  744. }
  745. //
  746. // Token cache
  747. //
  748. m_pTokenCache = new TOKEN_CACHE;
  749. if ( m_pTokenCache != NULL )
  750. {
  751. hr = m_pTokenCache->Initialize();
  752. if ( FAILED( hr ) )
  753. {
  754. delete m_pTokenCache;
  755. m_pTokenCache = NULL;
  756. }
  757. }
  758. if ( m_pTokenCache == NULL )
  759. {
  760. goto Failure;
  761. }
  762. //
  763. // File cache
  764. //
  765. m_pFileCache = new W3_FILE_INFO_CACHE;
  766. if ( m_pFileCache != NULL )
  767. {
  768. hr = m_pFileCache->Initialize();
  769. if ( FAILED( hr ) )
  770. {
  771. delete m_pFileCache;
  772. m_pFileCache = NULL;
  773. }
  774. }
  775. if ( m_pFileCache == NULL )
  776. {
  777. goto Failure;
  778. }
  779. //
  780. // Metacache
  781. //
  782. m_pMetaCache = new W3_METADATA_CACHE;
  783. if ( m_pMetaCache != NULL )
  784. {
  785. hr = m_pMetaCache->Initialize();
  786. if ( FAILED( hr ) )
  787. {
  788. delete m_pMetaCache;
  789. m_pMetaCache = NULL;
  790. }
  791. }
  792. if ( m_pMetaCache == NULL )
  793. {
  794. goto Failure;
  795. }
  796. //
  797. // UL response cache
  798. //
  799. m_pUlCache = new UL_RESPONSE_CACHE;
  800. if ( m_pUlCache != NULL )
  801. {
  802. hr = m_pUlCache->Initialize();
  803. if ( FAILED( hr ) )
  804. {
  805. delete m_pUlCache;
  806. m_pUlCache = NULL;
  807. }
  808. }
  809. if ( m_pUlCache == NULL )
  810. {
  811. goto Failure;
  812. }
  813. //
  814. // Now initialize the manager and register the caches
  815. //
  816. DBG_ASSERT( m_pMetaBase != NULL );
  817. hr = W3CacheInitialize( m_pMetaBase );
  818. if ( FAILED( hr ) )
  819. {
  820. goto Failure;
  821. }
  822. fCacheInit = TRUE;
  823. hr = W3CacheRegisterCache( m_pMetaCache );
  824. if ( FAILED( hr ) )
  825. {
  826. goto Failure;
  827. }
  828. hr = W3CacheRegisterCache( m_pFileCache );
  829. if ( FAILED( hr ) )
  830. {
  831. goto Failure;
  832. }
  833. hr = W3CacheRegisterCache( m_pTokenCache );
  834. if ( FAILED( hr ) )
  835. {
  836. goto Failure;
  837. }
  838. hr = W3CacheRegisterCache( m_pUrlInfoCache );
  839. if ( FAILED( hr ) )
  840. {
  841. goto Failure;
  842. }
  843. hr = W3CacheRegisterCache( m_pUlCache );
  844. if ( FAILED( hr ) )
  845. {
  846. goto Failure;
  847. }
  848. return NO_ERROR;
  849. Failure:
  850. if ( fCacheInit )
  851. {
  852. W3CacheTerminate();
  853. }
  854. if ( m_pMetaCache != NULL )
  855. {
  856. delete m_pMetaCache;
  857. m_pMetaCache = NULL;
  858. }
  859. if ( m_pFileCache != NULL )
  860. {
  861. delete m_pFileCache;
  862. m_pFileCache = NULL;
  863. }
  864. if ( m_pTokenCache != NULL )
  865. {
  866. delete m_pTokenCache;
  867. m_pTokenCache = NULL;
  868. }
  869. if ( m_pUrlInfoCache != NULL )
  870. {
  871. delete m_pUrlInfoCache;
  872. m_pUrlInfoCache = NULL;
  873. }
  874. if ( m_pUlCache != NULL )
  875. {
  876. delete m_pUlCache;
  877. m_pUlCache = NULL;
  878. }
  879. return hr;
  880. }
  881. HRESULT
  882. W3_SERVER::HandleMetabaseChange(
  883. const MD_CHANGE_OBJECT & ChangeObject
  884. )
  885. /*++
  886. Routine Description:
  887. Handle change notifications from the metabase.
  888. The change object will contain a change to
  889. /LM/W3SVC/ or lower in the metabase tree.
  890. Changes to /LM/W3SVC/ may alter W3_SERVER and
  891. are passed to all sites in the site list.
  892. Changes to /LM/W3SVC/{site id}/ or lower will
  893. affect only one site so are just passed on.
  894. Arguments:
  895. ChangeObject
  896. Return Value:
  897. CODEWORK - Partial implementation 1/26/00 - TaylorW
  898. --*/
  899. {
  900. DBGPRINTF(( DBG_CONTEXT,
  901. "W3_SERVER Notfied - Path(%S) Type(%d) NumIds(%08x)\n",
  902. ChangeObject.pszMDPath,
  903. ChangeObject.dwMDChangeType,
  904. ChangeObject.dwMDNumDataIDs
  905. ));
  906. HRESULT hr = NOERROR;
  907. BOOL IsPathW3 = FALSE;
  908. BOOL IsPathSite = FALSE;
  909. //
  910. // Find the instance id if present
  911. //
  912. DWORD SiteId;
  913. LPWSTR SiteIdString = ChangeObject.pszMDPath + W3_SERVER_MB_PATH_CCH;
  914. LPWSTR StringEnd;
  915. if( SiteIdString[0] == L'\0' )
  916. {
  917. IsPathW3 = TRUE;
  918. }
  919. else
  920. {
  921. SiteId = wcstoul( SiteIdString, &StringEnd, 10 );
  922. if( SiteId != 0 )
  923. {
  924. IsPathSite = TRUE;
  925. }
  926. }
  927. W3_SITE * Site = NULL;
  928. LK_RETCODE lkrc;
  929. if( IsPathSite )
  930. {
  931. //
  932. // We just need to notify a specific site
  933. //
  934. DBG_ASSERT( SiteId );
  935. Site = FindSite(SiteId);
  936. if (Site != NULL)
  937. {
  938. hr = Site->HandleMetabaseChange( ChangeObject );
  939. Site->Release();
  940. }
  941. }
  942. else if( IsPathW3 )
  943. {
  944. //
  945. // We need to notify every site
  946. //
  947. m_pSiteList->WriteLock();
  948. W3_SITE_LIST TempSiteList;
  949. for (W3_SITE_LIST::iterator iter = m_pSiteList->begin();
  950. iter != m_pSiteList->end();
  951. ++iter)
  952. {
  953. Site = iter.Record();
  954. Site->HandleMetabaseChange( ChangeObject, &TempSiteList );
  955. }
  956. m_pSiteList->Clear();
  957. m_cSites = 0;
  958. for (W3_SITE_LIST::iterator iter = TempSiteList.begin();
  959. iter != TempSiteList.end();
  960. ++iter)
  961. {
  962. Site = iter.Record();
  963. AddSite(Site);
  964. }
  965. m_pSiteList->WriteUnlock();
  966. //
  967. // Handle changes to this object's data
  968. //
  969. // At this point all we care about is data changes
  970. //
  971. if( (ChangeObject.dwMDChangeType & MD_CHANGE_TYPE_DELETE_DATA) ||
  972. (ChangeObject.dwMDChangeType & MD_CHANGE_TYPE_SET_DATA) )
  973. {
  974. //
  975. // CODEWORK: Handle changes to W3_SERVER metadata
  976. // Probably this is just the inprocess isapi list
  977. //
  978. }
  979. }
  980. // BUGBUG - Ignore Errors
  981. return S_OK;
  982. }
  983. //static
  984. VOID
  985. W3_SERVER::OnShutdown(
  986. BOOL fDoImmediate
  987. )
  988. /*++
  989. Routine Description:
  990. Called right after IPM indication of shutdown (but before drain)
  991. Arguments:
  992. None
  993. Return Value:
  994. None
  995. --*/
  996. {
  997. if (g_pW3Server->m_fInBackwardCompatibilityMode)
  998. {
  999. RAW_CONNECTION::StopListening();
  1000. }
  1001. if (fDoImmediate)
  1002. {
  1003. W3_CGI_HANDLER::KillAllCgis();
  1004. }
  1005. }
  1006. HRESULT W3_SERVER::CollectCounters(PBYTE *ppCounterData,
  1007. DWORD *pdwCounterData)
  1008. {
  1009. //
  1010. // Initialize to null
  1011. //
  1012. *ppCounterData = NULL;
  1013. *pdwCounterData = 0;
  1014. //
  1015. // Make sure we have enough memory
  1016. //
  1017. DWORD dwCounterBufferNeeded = sizeof(IISWPSiteCounters) * m_cSites +
  1018. sizeof(IISWPGlobalCounters) + sizeof(ULONGLONG);
  1019. if (m_pCounterDataBuffer == NULL)
  1020. {
  1021. m_pCounterDataBuffer = (PBYTE)LocalAlloc(LMEM_FIXED, dwCounterBufferNeeded);
  1022. if (m_pCounterDataBuffer == NULL)
  1023. {
  1024. return HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
  1025. }
  1026. m_dwCounterDataBuffer = dwCounterBufferNeeded;
  1027. }
  1028. else if (m_dwCounterDataBuffer < dwCounterBufferNeeded)
  1029. {
  1030. m_pCounterDataBuffer = (PBYTE)LocalReAlloc(m_pCounterDataBuffer,
  1031. dwCounterBufferNeeded,
  1032. LMEM_MOVEABLE);
  1033. if (m_pCounterDataBuffer == NULL)
  1034. {
  1035. return HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
  1036. }
  1037. m_dwCounterDataBuffer = dwCounterBufferNeeded;
  1038. }
  1039. m_pSiteList->ReadLock();
  1040. //
  1041. // Get the Site counters
  1042. //
  1043. DWORD i = 0;
  1044. for (W3_SITE_LIST::iterator iter = m_pSiteList->begin();
  1045. iter != m_pSiteList->end();
  1046. ++iter, ++i)
  1047. {
  1048. //
  1049. // In case some more new sites got added in between, skip them for now
  1050. //
  1051. if ((i+1)*sizeof(IISWPSiteCounters) + sizeof(IISWPGlobalCounters) >=
  1052. m_dwCounterDataBuffer)
  1053. {
  1054. break;
  1055. }
  1056. W3_SITE *pSite = iter.Record();
  1057. pSite->GetStatistics((IISWPSiteCounters *)
  1058. (m_pCounterDataBuffer +
  1059. i*sizeof(IISWPSiteCounters) + sizeof(DWORD)));
  1060. }
  1061. m_pSiteList->ReadUnlock();
  1062. //
  1063. // Set the number of sites
  1064. //
  1065. *(DWORD *)m_pCounterDataBuffer = i;
  1066. //
  1067. // Get the Global counters
  1068. //
  1069. IISWPGlobalCounters *pCacheCtrs = (IISWPGlobalCounters *)
  1070. (m_pCounterDataBuffer + i*sizeof(IISWPSiteCounters) + sizeof(DWORD));
  1071. //
  1072. // This contains some ULONGLONG values so align it, this is how WAS
  1073. // expects it
  1074. //
  1075. pCacheCtrs = (IISWPGlobalCounters *)(((DWORD_PTR)pCacheCtrs + 7) & ~7);
  1076. GetCacheStatistics(pCacheCtrs);
  1077. *ppCounterData = m_pCounterDataBuffer;
  1078. *pdwCounterData = DIFF((LPBYTE)pCacheCtrs - m_pCounterDataBuffer) + sizeof(IISWPGlobalCounters);
  1079. return S_OK;
  1080. }
  1081. VOID
  1082. W3_SERVER::GetCacheStatistics(
  1083. IISWPGlobalCounters * pCacheCtrs
  1084. )
  1085. /*++
  1086. Routine Description:
  1087. Get cache statistics for perfmon purposes
  1088. Arguments:
  1089. pCacheCtrs - Receives the statistics for cache
  1090. Notes:
  1091. CacheBytesTotal and CacheBytesInUse are not kept on a per-server basis
  1092. so they are only returned when retrieving summary statistics.
  1093. Returns:
  1094. None
  1095. --*/
  1096. {
  1097. //
  1098. // Get file cache statistics
  1099. //
  1100. if ( m_pFileCache != NULL )
  1101. {
  1102. pCacheCtrs->CurrentFilesCached = m_pFileCache->PerfQueryCurrentEntryCount();
  1103. pCacheCtrs->TotalFilesCached = m_pFileCache->PerfQueryTotalEntriesCached();
  1104. pCacheCtrs->FileCacheHits = m_pFileCache->PerfQueryHits();
  1105. pCacheCtrs->FileCacheMisses = m_pFileCache->PerfQueryMisses();
  1106. pCacheCtrs->FileCacheFlushes = m_pFileCache->PerfQueryFlushCalls();
  1107. pCacheCtrs->ActiveFlushedFiles = m_pFileCache->PerfQueryActiveFlushedEntries();
  1108. pCacheCtrs->TotalFlushedFiles = m_pFileCache->PerfQueryFlushes();
  1109. pCacheCtrs->CurrentFileCacheMemoryUsage = m_pFileCache->PerfQueryCurrentMemCacheSize();
  1110. pCacheCtrs->MaxFileCacheMemoryUsage = m_pFileCache->PerfQueryMaxMemCacheSize();
  1111. }
  1112. //
  1113. // Get URI cache statistics
  1114. //
  1115. if ( m_pUrlInfoCache != NULL )
  1116. {
  1117. pCacheCtrs->CurrentUrisCached = m_pUrlInfoCache->PerfQueryCurrentEntryCount();
  1118. pCacheCtrs->TotalUrisCached = m_pUrlInfoCache->PerfQueryTotalEntriesCached();
  1119. pCacheCtrs->UriCacheHits = m_pUrlInfoCache->PerfQueryHits();
  1120. pCacheCtrs->UriCacheMisses = m_pUrlInfoCache->PerfQueryMisses();
  1121. pCacheCtrs->UriCacheFlushes = m_pUrlInfoCache->PerfQueryFlushCalls();
  1122. pCacheCtrs->TotalFlushedUris = m_pUrlInfoCache->PerfQueryFlushes();
  1123. }
  1124. //
  1125. // BLOB cache counters (actually since there is no blob cache we will
  1126. // sub in the metacache counters which are more interesting since
  1127. // metacache misses are really painful
  1128. //
  1129. if ( m_pMetaCache != NULL )
  1130. {
  1131. pCacheCtrs->CurrentBlobsCached = m_pMetaCache->PerfQueryCurrentEntryCount();
  1132. pCacheCtrs->TotalBlobsCached = m_pMetaCache->PerfQueryTotalEntriesCached();
  1133. pCacheCtrs->BlobCacheHits = m_pMetaCache->PerfQueryHits();
  1134. pCacheCtrs->BlobCacheMisses = m_pMetaCache->PerfQueryMisses();
  1135. pCacheCtrs->BlobCacheFlushes = m_pMetaCache->PerfQueryFlushCalls();
  1136. pCacheCtrs->TotalFlushedBlobs = m_pMetaCache->PerfQueryFlushes();
  1137. }
  1138. }
  1139. HRESULT
  1140. W3_SERVER::ReadUseDigestSSP(
  1141. VOID
  1142. )
  1143. /*++
  1144. Routine description:
  1145. Read the UseDigestSSP property from the metabase
  1146. Arguments:
  1147. none
  1148. Return Value:
  1149. HRESULT
  1150. --*/
  1151. {
  1152. MB mb( QueryMDObject() );
  1153. if ( !mb.Open( QueryMDPath() ) )
  1154. {
  1155. return HRESULT_FROM_WIN32(GetLastError());
  1156. }
  1157. if ( !mb.GetDword( L"",
  1158. MD_USE_DIGEST_SSP,
  1159. IIS_MD_UT_SERVER,
  1160. ( DWORD * )&m_fUseDigestSSP,
  1161. 0 ) )
  1162. {
  1163. m_fUseDigestSSP = TRUE;
  1164. }
  1165. return S_OK;
  1166. }