Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2205 lines
51 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. #include "dav_handler.h"
  15. /*++
  16. class MB_LISTENER
  17. Implements a metabase change listener for W3_SERVER.
  18. --*/
  19. class MB_LISTENER
  20. : public MB_BASE_NOTIFICATION_SINK
  21. {
  22. public:
  23. MB_LISTENER( W3_SERVER * pParent )
  24. : m_pParent( pParent )
  25. {
  26. }
  27. STDMETHOD( SynchronizedSinkNotify )(
  28. DWORD dwMDNumElements,
  29. MD_CHANGE_OBJECT pcoChangeList[]
  30. )
  31. {
  32. return m_pParent->MetabaseChangeNotification( dwMDNumElements, pcoChangeList );
  33. }
  34. private:
  35. W3_SERVER * m_pParent;
  36. };
  37. W3_SERVER::W3_SERVER( BOOL fCompatibilityMode )
  38. : m_Signature (W3_SERVER_SIGNATURE),
  39. m_pMetaBase (NULL),
  40. m_InitStatus (INIT_NONE),
  41. m_fInBackwardCompatibilityMode(fCompatibilityMode),
  42. m_fUseDigestSSP (FALSE),
  43. m_EventLog (L"W3SVC-WP"),
  44. m_pCounterDataBuffer (NULL),
  45. m_dwCounterDataBuffer (0),
  46. m_cSites (0),
  47. m_hResourceDll (NULL),
  48. m_pTokenCache (NULL),
  49. m_pDigestContextCache (NULL),
  50. m_pUlCache (NULL),
  51. m_pUrlInfoCache (NULL),
  52. m_pFileCache (NULL),
  53. m_pMetaCache (NULL),
  54. m_pIsapiRestrictionList (NULL),
  55. m_pCgiRestrictionList (NULL),
  56. m_pOneSite (NULL),
  57. m_fDavEnabled (FALSE),
  58. m_fDoCentralBinaryLogging (FALSE),
  59. m_fTraceEnabled (FALSE)
  60. {
  61. }
  62. W3_SERVER::~W3_SERVER()
  63. {
  64. if (m_pCounterDataBuffer != NULL)
  65. {
  66. LocalFree(m_pCounterDataBuffer);
  67. m_pCounterDataBuffer = NULL;
  68. }
  69. m_Signature = W3_SERVER_FREE_SIGNATURE;
  70. }
  71. // static
  72. DWORD W3_SITE_LIST::ExtractKey(const W3_SITE *site)
  73. {
  74. return site->QueryId();
  75. }
  76. // static
  77. VOID W3_SITE_LIST::AddRefRecord(W3_SITE *site, int nIncr)
  78. {
  79. if (nIncr > 0)
  80. {
  81. site->ReferenceSite();
  82. }
  83. else if (nIncr < 0)
  84. {
  85. site->DereferenceSite();
  86. }
  87. else
  88. {
  89. DBG_ASSERT( !"Invalid reference");
  90. }
  91. }
  92. HRESULT
  93. W3_RESTRICTION_LIST::Create(MULTISZ * pmszList, RESTRICTION_LIST_TYPE ListType)
  94. {
  95. LPCWSTR szData = NULL;
  96. LPWSTR pCursor;
  97. LPWSTR pDelimiter;
  98. W3_IMAGE_RECORD * pNewRecord = NULL;
  99. LK_RETCODE lkr;
  100. HRESULT hr = NOERROR;
  101. BOOL fAllowItem;
  102. BOOL fFoundDefault = FALSE;
  103. STACK_STRU( struEntry,256 );
  104. DBG_ASSERT( pmszList );
  105. DBG_ASSERT( ListType == IsapiRestrictionList ||
  106. ListType == CgiRestrictionList );
  107. //
  108. // Set default to disallow unlisted items
  109. //
  110. _fAllowUnknown = FALSE;
  111. //
  112. // Initialize szData to the first element in the list
  113. //
  114. szData = pmszList->First();
  115. if ( szData == NULL )
  116. {
  117. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  118. }
  119. //
  120. // Walk the list and add items
  121. //
  122. do
  123. {
  124. hr = struEntry.Copy( szData );
  125. if ( FAILED( hr ) )
  126. {
  127. return hr;
  128. }
  129. //
  130. // Figure out if this is an allow or deny entry
  131. //
  132. pCursor = struEntry.QueryStr();
  133. pDelimiter = wcschr( pCursor, L',' );
  134. if ( !pDelimiter )
  135. {
  136. DBGPRINTF(( DBG_CONTEXT,
  137. "Invalid entry in restriction list and will be ignored: '%S'\r\n",
  138. szData ));
  139. continue;
  140. }
  141. *pDelimiter = L'\0';
  142. if ( wcscmp( pCursor, L"0" ) == 0 )
  143. {
  144. fAllowItem = FALSE;
  145. }
  146. else if ( wcscmp( pCursor, L"1" ) == 0 )
  147. {
  148. fAllowItem = TRUE;
  149. }
  150. else
  151. {
  152. //
  153. // Invalid value. Assume it's a deny entry
  154. //
  155. DBGPRINTF(( DBG_CONTEXT,
  156. "Invalid allow/deny flag in restriction list assumed to be '0': '%S'\r\n",
  157. szData ));
  158. fAllowItem = FALSE;
  159. }
  160. //
  161. // Get the image name. Check for special case entry
  162. // "*.dll" or ISAPI, or "*.exe" for CGI.
  163. //
  164. pCursor = pDelimiter + 1;
  165. pDelimiter = wcschr( pCursor, L',' );
  166. if ( pDelimiter )
  167. {
  168. *pDelimiter = L'\0';
  169. }
  170. if ( ( ListType == IsapiRestrictionList && _wcsicmp( pCursor, L"*.dll" ) == 0 ) ||
  171. ( ListType == CgiRestrictionList && _wcsicmp( pCursor, L"*.exe" ) == 0 ) )
  172. {
  173. if ( !fFoundDefault )
  174. {
  175. _fAllowUnknown = fAllowItem;
  176. fFoundDefault = TRUE;
  177. }
  178. else
  179. {
  180. //
  181. // There are at least two entries that represent
  182. // the default entry. We should assume that deny
  183. // entries take priority.
  184. //
  185. if ( _fAllowUnknown )
  186. {
  187. _fAllowUnknown = fAllowItem;
  188. }
  189. DBGPRINTF(( DBG_CONTEXT,
  190. "Duplicate default entry found in restriction list. "
  191. "'Deny' entries will take priority.\r\n" ));
  192. }
  193. continue;
  194. }
  195. //
  196. // Check to see if this entry already exists. If so,
  197. // deny entries should take priority.
  198. //
  199. lkr = FindKey( pCursor, &pNewRecord );
  200. if ( pNewRecord != NULL )
  201. {
  202. //
  203. // Found duplicate entry.
  204. //
  205. DBGPRINTF(( DBG_CONTEXT,
  206. "Duplicate entry for '%S' found in restriction list. "
  207. "'Deny' entries will take priority.\r\n",
  208. pCursor ));
  209. if ( pNewRecord->QueryIsAllowed() == TRUE )
  210. {
  211. pNewRecord->SetAllowedFlag( fAllowItem );
  212. }
  213. pNewRecord->DereferenceImageRecord();
  214. pNewRecord = NULL;
  215. }
  216. else
  217. {
  218. //
  219. // Adding a new non-default entry to the list.
  220. //
  221. pNewRecord = new W3_IMAGE_RECORD;
  222. if ( pNewRecord == NULL )
  223. {
  224. return HRESULT_FROM_WIN32( ERROR_NOT_ENOUGH_MEMORY );
  225. }
  226. hr = pNewRecord->Create( pCursor, fAllowItem );
  227. if ( FAILED( hr ) )
  228. {
  229. pNewRecord->DereferenceImageRecord();
  230. pNewRecord = NULL;
  231. return hr;
  232. }
  233. lkr = InsertRecord( pNewRecord, TRUE );
  234. pNewRecord->DereferenceImageRecord();
  235. pNewRecord = NULL;
  236. if ( lkr != LK_SUCCESS && lkr != LK_KEY_EXISTS )
  237. {
  238. return E_FAIL;
  239. }
  240. }
  241. } while ( szData = pmszList->Next( szData ) );
  242. _fInitialized = TRUE;
  243. return NOERROR;
  244. }
  245. BOOL W3_RESTRICTION_LIST::IsImageEnabled(LPCWSTR szImage)
  246. {
  247. W3_IMAGE_RECORD * pRecord = NULL;
  248. LK_RETCODE lkr;
  249. BOOL fAllowImage = FALSE;
  250. //
  251. // If this object has not been initialized, then
  252. // all queries should return FALSE.
  253. //
  254. if ( _fInitialized == FALSE )
  255. {
  256. return FALSE;
  257. }
  258. //
  259. // Is the item in the list?
  260. //
  261. if ( Size() == 0 )
  262. {
  263. //
  264. // fast path to avoid lkrhash
  265. // restriction list is static
  266. // The only change happens on metabase change updates
  267. // but in that case the whole list is replaced
  268. //
  269. lkr = LK_NO_SUCH_KEY;
  270. }
  271. else
  272. {
  273. lkr = FindKey( szImage, &pRecord );
  274. }
  275. if ( lkr == LK_SUCCESS )
  276. {
  277. fAllowImage = pRecord->QueryIsAllowed();
  278. pRecord->DereferenceImageRecord();
  279. pRecord = NULL;
  280. }
  281. else
  282. {
  283. fAllowImage = _fAllowUnknown;
  284. }
  285. return fAllowImage;
  286. }
  287. HRESULT FakeCollectCounters(PBYTE *ppCounterData,
  288. DWORD *pdwCounterData)
  289. {
  290. return g_pW3Server->CollectCounters(ppCounterData,
  291. pdwCounterData);
  292. }
  293. HRESULT
  294. W3_SERVER::Initialize(
  295. INT argc,
  296. LPWSTR argv[]
  297. )
  298. /*++
  299. Routine Description:
  300. Initialize ULW3.DLL but do not begin listening for requests
  301. Arguments:
  302. argc - Command line argument count
  303. argv[] - Command line arguments (from WAS)
  304. Return Value:
  305. HRESULT
  306. --*/
  307. {
  308. HRESULT hr = NOERROR;
  309. ULONG err;
  310. ULATQ_CONFIG ulatqConfig;
  311. WSADATA wsaData;
  312. ULONG_PTR commandLaunch;
  313. HKEY hKey;
  314. DWORD dwType;
  315. DWORD cbTraceEnabled;
  316. DWORD dwTraceEnabled;
  317. DBGPRINTF((
  318. DBG_CONTEXT,
  319. "Initializing the W3 Server Started CTC = %d \n",
  320. GetTickCount()
  321. ));
  322. //
  323. // Initialize Computer name, trivial so doesn't need its own state
  324. //
  325. DWORD cbSize = sizeof m_pszComputerName;
  326. if (!GetComputerNameA(m_pszComputerName, &cbSize))
  327. {
  328. strcpy(m_pszComputerName, "<Server>");
  329. }
  330. m_cchComputerName = (USHORT)strlen(m_pszComputerName);
  331. //
  332. // Figure out whether TRACE requests are enabled
  333. //
  334. if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  335. W3_PARAMETERS_KEY,
  336. 0,
  337. KEY_READ,
  338. &hKey ) == NO_ERROR )
  339. {
  340. cbTraceEnabled = sizeof( DWORD );
  341. if ( RegQueryValueEx( hKey,
  342. L"EnableTraceMethod",
  343. NULL,
  344. &dwType,
  345. (LPBYTE) &dwTraceEnabled,
  346. &cbTraceEnabled ) == NO_ERROR )
  347. {
  348. m_fTraceEnabled = !!dwTraceEnabled;
  349. }
  350. RegCloseKey( hKey );
  351. }
  352. //
  353. // Keep track of how much we have initialized so that we can cleanup
  354. // only that which is necessary
  355. //
  356. m_InitStatus = INIT_NONE;
  357. m_hResourceDll = LoadLibrary(IIS_RESOURCE_DLL_NAME);
  358. if ( m_hResourceDll == NULL )
  359. {
  360. hr = HRESULT_FROM_WIN32( GetLastError() );
  361. DBGPRINTF(( DBG_CONTEXT,
  362. "Error Loading required resource DLL. hr = %x\n",
  363. hr ));
  364. goto exit;
  365. }
  366. //
  367. // Initialize IISUTIL
  368. //
  369. if ( !InitializeIISUtil() )
  370. {
  371. hr = HRESULT_FROM_WIN32( GetLastError() );
  372. DBGPRINTF(( DBG_CONTEXT,
  373. "Error initializing IISUTIL. hr = %x\n",
  374. hr ));
  375. goto exit;
  376. }
  377. m_InitStatus = INIT_IISUTIL;
  378. DBGPRINTF((
  379. DBG_CONTEXT,
  380. "W3 Server initializing WinSock. CTC = %d \n",
  381. GetTickCount()
  382. ));
  383. //
  384. // Initialize WinSock
  385. //
  386. if ( ( err = WSAStartup( MAKEWORD( 1, 1 ), &wsaData ) ) != ERROR_SUCCESS )
  387. {
  388. hr = HRESULT_FROM_WIN32( err );
  389. DBGPRINTF(( DBG_CONTEXT,
  390. "Error initializing WinSock. hr = %x\n",
  391. hr ));
  392. goto exit;
  393. }
  394. m_InitStatus = INIT_WINSOCK;
  395. DBGPRINTF((
  396. DBG_CONTEXT,
  397. "W3 Server WinSock initialized. CTC = %d \n",
  398. GetTickCount()
  399. ));
  400. //
  401. // Initialize the metabase access (ABO)
  402. //
  403. hr = CoCreateInstance( CLSID_MSAdminBase,
  404. NULL,
  405. CLSCTX_SERVER,
  406. IID_IMSAdminBase,
  407. (LPVOID *)&(m_pMetaBase)
  408. );
  409. if( FAILED(hr) )
  410. {
  411. DBGPRINTF(( DBG_CONTEXT,
  412. "Error creating ABO object. hr = %x\n",
  413. hr ));
  414. goto exit;
  415. }
  416. hr = ReadUseDigestSSP();
  417. if( FAILED(hr) )
  418. {
  419. DBGPRINTF(( DBG_CONTEXT,
  420. "Error reading UseDigestSSP property. hr = %x\n",
  421. hr ));
  422. goto exit;
  423. }
  424. m_pMetaBase->GetSystemChangeNumber( &m_dwSystemChangeNumber );
  425. m_InitStatus = INIT_METABASE;
  426. DBGPRINTF((
  427. DBG_CONTEXT,
  428. "W3 Server Metabase initialized. CTC = %d \n",
  429. GetTickCount()
  430. ));
  431. //
  432. // Initialize metabase change notification mechanism
  433. //
  434. m_pMetabaseListener = new MB_LISTENER( this );
  435. if ( m_pMetabaseListener == NULL )
  436. {
  437. hr = HRESULT_FROM_WIN32( ERROR_NOT_ENOUGH_MEMORY );
  438. goto exit;
  439. }
  440. m_InitStatus = INIT_MB_LISTENER;
  441. //
  442. // Initialize W3_SITE
  443. //
  444. hr = W3_SITE::W3SiteInitialize();
  445. if ( FAILED( hr ) )
  446. {
  447. DBGPRINTF(( DBG_CONTEXT,
  448. "Error doing global W3_SITE initialization. hr = %x\n",
  449. hr ));
  450. goto exit;
  451. }
  452. m_InitStatus = INIT_W3_SITE;
  453. //
  454. // Initialize ULATQ
  455. //
  456. ulatqConfig.pfnNewRequest = W3_MAIN_CONTEXT::OnNewRequest;
  457. ulatqConfig.pfnIoCompletion = W3_MAIN_CONTEXT::OnIoCompletion;
  458. ulatqConfig.pfnDisconnect = OnUlDisconnect;
  459. ulatqConfig.pfnOnShutdown = W3_SERVER::OnShutdown;
  460. ulatqConfig.pfnCollectCounters = FakeCollectCounters;
  461. hr = UlAtqInitialize( argc,
  462. argv,
  463. &ulatqConfig );
  464. if( FAILED(hr) )
  465. {
  466. DBGPRINTF(( DBG_CONTEXT,
  467. "Error initializing ULATQ. hr = %x\n",
  468. hr ));
  469. // Since we most likely have not hooked up to WAS yet we need
  470. // to communicate that we failed to initialize either the communication
  471. // with HTTP or with WAS.
  472. g_pW3Server->LogEvent(
  473. W3_EVENT_FAIL_INITIALIZING_ULATQ,
  474. 0,
  475. NULL,
  476. hr
  477. );
  478. goto exit;
  479. }
  480. commandLaunch = (ULONG_PTR) UlAtqGetContextProperty( NULL,
  481. ULATQ_PROPERTY_IS_COMMAND_LINE_LAUNCH );
  482. m_fIsCommandLineLaunch = commandLaunch ? TRUE : FALSE;
  483. m_fDoCentralBinaryLogging = (ULONG_PTR) UlAtqGetContextProperty( NULL,
  484. ULATQ_PROPERTY_DO_CENTRAL_BINARY_LOGGING );
  485. m_InitStatus = INIT_ULATQ;
  486. DBGPRINTF((
  487. DBG_CONTEXT,
  488. "W3 Server UlAtq initialized (ipm has signalled). CTC = %d \n",
  489. GetTickCount()
  490. ));
  491. //
  492. // Initialize global filter list
  493. //
  494. hr = GlobalFilterInitialize();
  495. if ( FAILED( hr ) )
  496. {
  497. DBGPRINTF(( DBG_CONTEXT,
  498. "Error doing global filter initialization. hr = %x\n",
  499. hr ));
  500. goto exit;
  501. }
  502. m_InitStatus = INIT_FILTERS;
  503. //
  504. // Initialize site list
  505. //
  506. m_pSiteList = new W3_SITE_LIST();
  507. if ( m_pSiteList == NULL )
  508. {
  509. hr = HRESULT_FROM_WIN32( ERROR_NOT_ENOUGH_MEMORY );
  510. goto exit;
  511. }
  512. m_InitStatus = INIT_SITE_LIST;
  513. //
  514. // Initialize caches
  515. //
  516. hr = InitializeCaches();
  517. if ( FAILED( hr ) )
  518. {
  519. DBGPRINTF(( DBG_CONTEXT,
  520. "Error initializing caches. hr = %x\n",
  521. hr ));
  522. goto exit;
  523. }
  524. m_InitStatus = INIT_CACHES;
  525. //
  526. // Initialize connection table
  527. //
  528. hr = W3_CONNECTION::Initialize();
  529. if ( FAILED( hr ) )
  530. {
  531. DBGPRINTF(( DBG_CONTEXT,
  532. "Error initializing connection table. hr = %x\n",
  533. hr ));
  534. goto exit;
  535. }
  536. m_InitStatus = INIT_W3_CONNECTION;
  537. //
  538. // Initialize W3_CONTEXTs
  539. //
  540. hr = W3_CONTEXT::Initialize();
  541. if ( FAILED( hr ) )
  542. {
  543. DBGPRINTF(( DBG_CONTEXT,
  544. "Error initializing W3_CONTEXT globals. hr = %x\n",
  545. hr ));
  546. goto exit;
  547. }
  548. m_InitStatus = INIT_W3_CONTEXT;
  549. //
  550. // Initialize W3_REQUEST
  551. //
  552. hr = W3_REQUEST::Initialize();
  553. if ( FAILED( hr ) )
  554. {
  555. DBGPRINTF(( DBG_CONTEXT,
  556. "Error initializing W3_REQUEST globals. hr = %x\n",
  557. hr ));
  558. goto exit;
  559. }
  560. m_InitStatus = INIT_W3_REQUEST;
  561. //
  562. // Initialize W3_RESPONSE
  563. //
  564. hr = W3_RESPONSE::Initialize();
  565. if ( FAILED( hr ) )
  566. {
  567. DBGPRINTF(( DBG_CONTEXT,
  568. "Error initializing W3_RESPONSE globals. hr = %x\n",
  569. hr ));
  570. goto exit;
  571. }
  572. m_InitStatus = INIT_W3_RESPONSE;
  573. //
  574. // Initialize server variables
  575. //
  576. hr = SERVER_VARIABLE_HASH::Initialize();
  577. if ( FAILED( hr ) )
  578. {
  579. DBGPRINTF(( DBG_CONTEXT,
  580. "Error initializing server variable hash table. hr = %x\n",
  581. hr ));
  582. goto exit;
  583. }
  584. m_InitStatus = INIT_SERVER_VARIABLES;
  585. //
  586. // Initialize Mime-mappings
  587. //
  588. hr = InitializeMimeMap();
  589. if ( FAILED( hr ) )
  590. {
  591. DBGPRINTF(( DBG_CONTEXT,
  592. "Error initializing mime map table. hr = %x\n",
  593. hr ));
  594. goto exit;
  595. }
  596. m_InitStatus = INIT_MIME_MAP;
  597. //
  598. // Initialize logging
  599. //
  600. if (FAILED(hr = LOGGING::Initialize()))
  601. {
  602. goto exit;
  603. }
  604. m_InitStatus = INIT_LOGGING;
  605. //
  606. // If we are in backward compatibility mode, then initialize stream
  607. // filter here
  608. //
  609. if (m_fInBackwardCompatibilityMode)
  610. {
  611. hr = RAW_CONNECTION::Initialize();
  612. if ( FAILED( hr ) )
  613. {
  614. DBGPRINTF(( DBG_CONTEXT,
  615. "Error initialize ISAPI raw data filter support. hr = %x\n",
  616. hr ));
  617. goto exit;
  618. }
  619. }
  620. m_InitStatus = INIT_RAW_CONNECTION;
  621. //
  622. // Client certificate object wrapper
  623. //
  624. hr = CERTIFICATE_CONTEXT::Initialize();
  625. if ( FAILED( hr ) )
  626. {
  627. DBGPRINTF(( DBG_CONTEXT,
  628. "Error initializing certificate contexts. hr = %x\n",
  629. hr ));
  630. goto exit;
  631. }
  632. m_InitStatus = INIT_CERTIFICATE_CONTEXT;
  633. //
  634. // Gateway Restriction Lists
  635. //
  636. hr = InitializeRestrictionList( IsapiRestrictionList );
  637. if ( FAILED( hr ) )
  638. {
  639. DBGPRINTF(( DBG_CONTEXT,
  640. "Error initializing ISAPI restriction list. hr = %x\n",
  641. hr ));
  642. goto exit;
  643. }
  644. m_InitStatus = INIT_ISAPI_RESTRICTION_LIST;
  645. hr = InitializeRestrictionList( CgiRestrictionList );
  646. if ( FAILED( hr ) )
  647. {
  648. DBGPRINTF(( DBG_CONTEXT,
  649. "Error initializing CGI restriction list. hr = %x\n",
  650. hr ));
  651. goto exit;
  652. }
  653. m_InitStatus = INIT_CGI_RESTRICTION_LIST;
  654. //
  655. // Initialize Http Compression
  656. // Ignore failure but remember if we Initialized.
  657. //
  658. hr = HTTP_COMPRESSION::Initialize();
  659. if ( FAILED( hr ) )
  660. {
  661. DBGPRINTF(( DBG_CONTEXT,
  662. "Error initializing Http Compression. hr = %x\n",
  663. hr ));
  664. hr = S_OK;
  665. }
  666. else
  667. {
  668. m_InitStatus = INIT_HTTP_COMPRESSION;
  669. }
  670. exit:
  671. return hr;
  672. }
  673. VOID
  674. W3_SERVER::Terminate(
  675. HRESULT hrReason
  676. )
  677. /*++
  678. Routine Description:
  679. Terminate ULW3 globals. This should be done after we have stopped
  680. listening for new requests (duh)
  681. Arguments:
  682. None
  683. Return Value:
  684. TRUE if successful, else FALSE
  685. --*/
  686. {
  687. DBGPRINTF(( DBG_CONTEXT,
  688. "Terminating W3_SERVER object\n" ));
  689. switch( m_InitStatus )
  690. {
  691. case INIT_HTTP_COMPRESSION:
  692. HTTP_COMPRESSION::Terminate();
  693. case INIT_CGI_RESTRICTION_LIST:
  694. m_CgiRestrictionLock.WriteLock();
  695. if ( m_pCgiRestrictionList != NULL )
  696. {
  697. m_pCgiRestrictionList->DereferenceRestrictionList();
  698. m_pCgiRestrictionList = NULL;
  699. }
  700. m_CgiRestrictionLock.WriteUnlock();
  701. case INIT_ISAPI_RESTRICTION_LIST:
  702. m_IsapiRestrictionLock.WriteLock();
  703. if ( m_pIsapiRestrictionList != NULL )
  704. {
  705. m_pIsapiRestrictionList->DereferenceRestrictionList();
  706. m_pIsapiRestrictionList = NULL;
  707. }
  708. m_IsapiRestrictionLock.WriteUnlock();
  709. case INIT_CERTIFICATE_CONTEXT:
  710. CERTIFICATE_CONTEXT::Terminate();
  711. case INIT_RAW_CONNECTION:
  712. if (m_fInBackwardCompatibilityMode)
  713. {
  714. RAW_CONNECTION::Terminate();
  715. }
  716. case INIT_LOGGING:
  717. LOGGING::Terminate();
  718. case INIT_MIME_MAP:
  719. CleanupMimeMap();
  720. case INIT_SERVER_VARIABLES:
  721. SERVER_VARIABLE_HASH::Terminate();
  722. case INIT_W3_RESPONSE:
  723. W3_RESPONSE::Terminate();
  724. case INIT_W3_REQUEST:
  725. W3_REQUEST::Terminate();
  726. case INIT_W3_CONTEXT:
  727. W3_CONTEXT::Terminate();
  728. case INIT_W3_CONNECTION:
  729. W3_CONNECTION::Terminate();
  730. case INIT_CACHES:
  731. TerminateCaches();
  732. case INIT_SITE_LIST:
  733. //
  734. // Optimization for one site
  735. //
  736. m_OneSiteLock.WriteLock();
  737. if ( m_pOneSite != NULL )
  738. {
  739. m_pOneSite->DereferenceSite();
  740. m_pOneSite = NULL;
  741. }
  742. m_OneSiteLock.WriteUnlock();
  743. //
  744. // end of optimization for one site
  745. //
  746. delete m_pSiteList;
  747. m_pSiteList = NULL;
  748. case INIT_FILTERS:
  749. GlobalFilterTerminate();
  750. case INIT_ULATQ:
  751. UlAtqTerminate( hrReason );
  752. case INIT_W3_SITE:
  753. W3_SITE::W3SiteTerminate();
  754. case INIT_MB_LISTENER:
  755. if ( m_pMetabaseListener != NULL )
  756. {
  757. m_pMetabaseListener->Release();
  758. m_pMetabaseListener = NULL;
  759. }
  760. case INIT_METABASE:
  761. if ( m_pMetaBase )
  762. {
  763. m_pMetaBase->Release();
  764. }
  765. case INIT_WINSOCK:
  766. WSACleanup();
  767. case INIT_IISUTIL:
  768. TerminateIISUtil();
  769. }
  770. if (m_hResourceDll != NULL)
  771. {
  772. FreeLibrary(m_hResourceDll);
  773. m_hResourceDll = NULL;
  774. }
  775. m_InitStatus = INIT_NONE;
  776. }
  777. HRESULT
  778. W3_SERVER::LoadString(
  779. DWORD dwStringID,
  780. CHAR * pszString,
  781. DWORD * pcbString
  782. )
  783. /*++
  784. Routine Description:
  785. Load a resource string from W3CORE.DLL
  786. Arguments:
  787. dwStringID - String ID
  788. pszString - Filled with string
  789. pcbString - On input the size of the buffer pszString, on successful
  790. output, the length of the string copied to pszString
  791. Return Value:
  792. HRESULT
  793. --*/
  794. {
  795. DWORD cbCopied;
  796. if ( pszString == NULL ||
  797. pcbString == NULL )
  798. {
  799. DBG_ASSERT( FALSE );
  800. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  801. }
  802. cbCopied = LoadStringA( m_hResourceDll,
  803. dwStringID,
  804. pszString,
  805. *pcbString );
  806. if ( cbCopied == 0 )
  807. {
  808. return HRESULT_FROM_WIN32( GetLastError() );
  809. }
  810. *pcbString = cbCopied;
  811. return NO_ERROR;
  812. }
  813. HRESULT
  814. W3_SERVER::StartListen(
  815. VOID
  816. )
  817. /*++
  818. Routine Description:
  819. Begin listening for requests. This function will return once we have
  820. stopped listening for requests (due to WAS stopping us for some reason)
  821. Listen for metabase changes.
  822. Arguments:
  823. None
  824. Return Value:
  825. HRESULT
  826. --*/
  827. {
  828. HRESULT hr = NOERROR;
  829. DBG_ASSERT( m_pMetabaseListener );
  830. //
  831. // Starting getting metabase changes
  832. //
  833. hr = m_pMetabaseListener->StartListening( m_pMetaBase );
  834. if ( FAILED( hr ) )
  835. {
  836. DBGPRINTF(( DBG_CONTEXT,
  837. "Error trying to listen for metabase changes. hr = %x\n",
  838. hr ));
  839. return hr;
  840. }
  841. //
  842. // Listen for the stream filter
  843. //
  844. if (m_fInBackwardCompatibilityMode)
  845. {
  846. hr = RAW_CONNECTION::StartListening();
  847. if ( FAILED( hr ) )
  848. {
  849. DBGPRINTF(( DBG_CONTEXT,
  850. "Error listening on filter channel. hr = %x\n",
  851. hr ));
  852. m_pMetabaseListener->StopListening( m_pMetaBase );
  853. return hr;
  854. }
  855. }
  856. //
  857. // Start listening for requests
  858. //
  859. hr = UlAtqStartListen();
  860. if( FAILED( hr ) )
  861. {
  862. DBGPRINTF(( DBG_CONTEXT,
  863. "Error listening for HTTP requests. hr = %x\n",
  864. hr ));
  865. if (m_fInBackwardCompatibilityMode)
  866. {
  867. RAW_CONNECTION::StopListening();
  868. }
  869. m_pMetabaseListener->StopListening( m_pMetaBase );
  870. return hr;
  871. }
  872. //
  873. // StartListen() will return when we are to shutdown.
  874. //
  875. m_pMetabaseListener->StopListening( m_pMetaBase );
  876. return NO_ERROR;
  877. }
  878. W3_SITE *
  879. W3_SERVER::FindSite(
  880. DWORD dwInstance
  881. )
  882. {
  883. W3_SITE *site = NULL;
  884. //
  885. // Optimization for one site
  886. //
  887. if ( m_pOneSite != NULL )
  888. {
  889. m_OneSiteLock.ReadLock();
  890. // minimize the time spent under this critical section
  891. //
  892. if ( m_pOneSite != NULL )
  893. {
  894. m_pOneSite->ReferenceSite();
  895. site = m_pOneSite;
  896. }
  897. m_OneSiteLock.ReadUnlock();
  898. if ( site != NULL )
  899. {
  900. if ( site->QueryId() != dwInstance )
  901. {
  902. site->DereferenceSite();
  903. site = NULL;
  904. }
  905. return site;
  906. }
  907. }
  908. //
  909. // End of optimization for one site
  910. //
  911. LK_RETCODE lkrc = m_pSiteList->FindKey(dwInstance, &site);
  912. if (site != NULL)
  913. {
  914. DBG_ASSERT(lkrc == LK_SUCCESS);
  915. }
  916. return site;
  917. }
  918. BOOL W3_SERVER::AddSite(W3_SITE *site,
  919. bool fOverWrite)
  920. {
  921. if (m_pSiteList->InsertRecord(site, fOverWrite) == LK_SUCCESS)
  922. {
  923. if (!fOverWrite)
  924. {
  925. InterlockedIncrement((LPLONG)&m_cSites);
  926. }
  927. //
  928. // optimization for SiteList with only one active site
  929. //
  930. m_OneSiteLock.WriteLock();
  931. if ( m_pOneSite != NULL )
  932. {
  933. m_pOneSite->DereferenceSite();
  934. m_pOneSite = NULL;
  935. }
  936. if ( m_cSites == 1 )
  937. {
  938. site->ReferenceSite();
  939. m_pOneSite = site;
  940. }
  941. m_OneSiteLock.WriteUnlock();
  942. return TRUE;
  943. }
  944. return FALSE;
  945. }
  946. BOOL W3_SERVER::RemoveSite(W3_SITE *pInstance)
  947. {
  948. if (m_pSiteList->DeleteRecord(pInstance) == LK_SUCCESS)
  949. {
  950. InterlockedDecrement((LPLONG)&m_cSites);
  951. //
  952. // optimization for SiteList with only one active site
  953. //
  954. if ( m_pOneSite != NULL )
  955. {
  956. m_OneSiteLock.WriteLock();
  957. if ( m_pOneSite != NULL )
  958. {
  959. m_pOneSite->DereferenceSite();
  960. m_pOneSite = NULL;
  961. }
  962. m_OneSiteLock.WriteUnlock();
  963. }
  964. return TRUE;
  965. }
  966. return FALSE;
  967. }
  968. void W3_SERVER::DestroyAllSites()
  969. {
  970. m_OneSiteLock.WriteLock();
  971. if ( m_pOneSite != NULL )
  972. {
  973. m_pOneSite->DereferenceSite();
  974. m_pOneSite = NULL;
  975. }
  976. m_OneSiteLock.WriteUnlock();
  977. m_pSiteList->Clear();
  978. }
  979. HRESULT
  980. W3_SERVER::MetabaseChangeNotification(
  981. DWORD dwMDNumElements,
  982. MD_CHANGE_OBJECT pcoChangeList[]
  983. )
  984. /*++
  985. Routine Description:
  986. This is the entry point for metabase changes.
  987. It just loops through pcoChangeList and passes
  988. the change to the handler method.
  989. Arguments:
  990. dwMDNumElements - Number of change objects
  991. pcoChangeList - Array of change objects
  992. Return Value:
  993. --*/
  994. {
  995. DBGPRINTF(( DBG_CONTEXT,
  996. "MetabaseChangeNotification called.\n"
  997. ));
  998. //
  999. // Verify that the change is for /LM/W3SVC/ or lower
  1000. // and dispatch the change.
  1001. //
  1002. HRESULT hr = NOERROR;
  1003. for( DWORD i = 0; i < dwMDNumElements; ++i )
  1004. {
  1005. if( _wcsnicmp( pcoChangeList[i].pszMDPath,
  1006. W3_SERVER_MB_PATH,
  1007. W3_SERVER_MB_PATH_CCH ) == 0 )
  1008. {
  1009. hr = HandleMetabaseChange( pcoChangeList[i] );
  1010. }
  1011. }
  1012. //
  1013. // Update system change number for use by file cache (etags)
  1014. //
  1015. m_pMetaBase->GetSystemChangeNumber( &m_dwSystemChangeNumber );
  1016. return hr;
  1017. }
  1018. VOID
  1019. W3_SERVER::TerminateCaches(
  1020. VOID
  1021. )
  1022. /*++
  1023. Routine Description:
  1024. Cleanup all the caches
  1025. Arguments:
  1026. None
  1027. Return Value:
  1028. None
  1029. --*/
  1030. {
  1031. //
  1032. // First flush all caches (only references which should remain on cached
  1033. // objects should be thru the hash tables themselves). Once we have
  1034. // flushed all the caches, all the cached objects should go away.
  1035. //
  1036. // If they don't that's a bug and ACache assert will fire
  1037. //
  1038. W3CacheFlushAllCaches();
  1039. //
  1040. // Now just unregister and cleanup the caches
  1041. //
  1042. if ( m_pMetaCache != NULL )
  1043. {
  1044. W3CacheUnregisterCache( m_pMetaCache );
  1045. m_pMetaCache->Terminate();
  1046. delete m_pMetaCache;
  1047. m_pMetaCache = NULL;
  1048. }
  1049. if ( m_pFileCache != NULL )
  1050. {
  1051. W3CacheUnregisterCache( m_pFileCache );
  1052. m_pFileCache->Terminate();
  1053. delete m_pFileCache;
  1054. m_pFileCache = NULL;
  1055. }
  1056. if ( m_pTokenCache != NULL )
  1057. {
  1058. W3CacheUnregisterCache( m_pTokenCache );
  1059. m_pTokenCache->Terminate();
  1060. delete m_pTokenCache;
  1061. m_pTokenCache = NULL;
  1062. }
  1063. if ( m_pDigestContextCache != NULL )
  1064. {
  1065. W3CacheUnregisterCache( m_pDigestContextCache );
  1066. m_pDigestContextCache->Terminate();
  1067. delete m_pDigestContextCache;
  1068. m_pDigestContextCache = NULL;
  1069. }
  1070. if ( m_pUrlInfoCache != NULL )
  1071. {
  1072. W3CacheUnregisterCache( m_pUrlInfoCache );
  1073. m_pUrlInfoCache->Terminate();
  1074. delete m_pUrlInfoCache;
  1075. m_pUrlInfoCache = NULL;
  1076. }
  1077. if ( m_pUlCache != NULL )
  1078. {
  1079. W3CacheUnregisterCache( m_pUlCache );
  1080. m_pUlCache->Terminate();
  1081. delete m_pUlCache;
  1082. m_pUlCache = NULL;
  1083. }
  1084. W3CacheTerminate();
  1085. }
  1086. HRESULT
  1087. W3_SERVER::InitializeCaches(
  1088. VOID
  1089. )
  1090. /*++
  1091. Routine Description:
  1092. Initialize caches
  1093. Arguments:
  1094. None
  1095. Return Value:
  1096. HRESULT
  1097. --*/
  1098. {
  1099. HRESULT hr = NO_ERROR;
  1100. BOOL fCacheInit = FALSE;
  1101. //
  1102. // Url cache
  1103. //
  1104. m_pUrlInfoCache = new W3_URL_INFO_CACHE;
  1105. if ( m_pUrlInfoCache != NULL )
  1106. {
  1107. hr = m_pUrlInfoCache->Initialize();
  1108. if ( FAILED( hr ) )
  1109. {
  1110. delete m_pUrlInfoCache;
  1111. m_pUrlInfoCache = NULL;
  1112. }
  1113. }
  1114. if ( m_pUrlInfoCache == NULL )
  1115. {
  1116. goto Failure;
  1117. }
  1118. //
  1119. // Token cache
  1120. //
  1121. m_pTokenCache = new TOKEN_CACHE;
  1122. if ( m_pTokenCache != NULL )
  1123. {
  1124. hr = m_pTokenCache->Initialize();
  1125. if ( FAILED( hr ) )
  1126. {
  1127. delete m_pTokenCache;
  1128. m_pTokenCache = NULL;
  1129. }
  1130. }
  1131. if ( m_pTokenCache == NULL )
  1132. {
  1133. goto Failure;
  1134. }
  1135. //
  1136. // Digest server context cache
  1137. //
  1138. m_pDigestContextCache = new DIGEST_CONTEXT_CACHE;
  1139. if ( m_pDigestContextCache != NULL )
  1140. {
  1141. hr = m_pDigestContextCache->Initialize();
  1142. if ( FAILED( hr ) )
  1143. {
  1144. delete m_pDigestContextCache;
  1145. m_pDigestContextCache = NULL;
  1146. }
  1147. }
  1148. if ( m_pDigestContextCache == NULL )
  1149. {
  1150. goto Failure;
  1151. }
  1152. //
  1153. // Digest server context cache
  1154. //
  1155. //
  1156. // File cache
  1157. //
  1158. m_pFileCache = new W3_FILE_INFO_CACHE;
  1159. if ( m_pFileCache != NULL )
  1160. {
  1161. hr = m_pFileCache->Initialize();
  1162. if ( FAILED( hr ) )
  1163. {
  1164. delete m_pFileCache;
  1165. m_pFileCache = NULL;
  1166. }
  1167. }
  1168. if ( m_pFileCache == NULL )
  1169. {
  1170. goto Failure;
  1171. }
  1172. //
  1173. // Metacache
  1174. //
  1175. m_pMetaCache = new W3_METADATA_CACHE;
  1176. if ( m_pMetaCache != NULL )
  1177. {
  1178. hr = m_pMetaCache->Initialize();
  1179. if ( FAILED( hr ) )
  1180. {
  1181. delete m_pMetaCache;
  1182. m_pMetaCache = NULL;
  1183. }
  1184. }
  1185. if ( m_pMetaCache == NULL )
  1186. {
  1187. goto Failure;
  1188. }
  1189. //
  1190. // UL response cache
  1191. //
  1192. m_pUlCache = new UL_RESPONSE_CACHE;
  1193. if ( m_pUlCache != NULL )
  1194. {
  1195. hr = m_pUlCache->Initialize();
  1196. if ( FAILED( hr ) )
  1197. {
  1198. delete m_pUlCache;
  1199. m_pUlCache = NULL;
  1200. }
  1201. }
  1202. if ( m_pUlCache == NULL )
  1203. {
  1204. goto Failure;
  1205. }
  1206. //
  1207. // Now initialize the manager and register the caches
  1208. //
  1209. DBG_ASSERT( m_pMetaBase != NULL );
  1210. hr = W3CacheInitialize( m_pMetaBase );
  1211. if ( FAILED( hr ) )
  1212. {
  1213. goto Failure;
  1214. }
  1215. fCacheInit = TRUE;
  1216. hr = W3CacheRegisterCache( m_pMetaCache );
  1217. if ( FAILED( hr ) )
  1218. {
  1219. goto Failure;
  1220. }
  1221. hr = W3CacheRegisterCache( m_pFileCache );
  1222. if ( FAILED( hr ) )
  1223. {
  1224. goto Failure;
  1225. }
  1226. hr = W3CacheRegisterCache( m_pTokenCache );
  1227. if ( FAILED( hr ) )
  1228. {
  1229. goto Failure;
  1230. }
  1231. hr = W3CacheRegisterCache( m_pDigestContextCache );
  1232. if ( FAILED( hr ) )
  1233. {
  1234. goto Failure;
  1235. }
  1236. hr = W3CacheRegisterCache( m_pUrlInfoCache );
  1237. if ( FAILED( hr ) )
  1238. {
  1239. goto Failure;
  1240. }
  1241. hr = W3CacheRegisterCache( m_pUlCache );
  1242. if ( FAILED( hr ) )
  1243. {
  1244. goto Failure;
  1245. }
  1246. return NO_ERROR;
  1247. Failure:
  1248. if ( fCacheInit )
  1249. {
  1250. W3CacheTerminate();
  1251. }
  1252. if ( m_pMetaCache != NULL )
  1253. {
  1254. delete m_pMetaCache;
  1255. m_pMetaCache = NULL;
  1256. }
  1257. if ( m_pFileCache != NULL )
  1258. {
  1259. delete m_pFileCache;
  1260. m_pFileCache = NULL;
  1261. }
  1262. if ( m_pTokenCache != NULL )
  1263. {
  1264. delete m_pTokenCache;
  1265. m_pTokenCache = NULL;
  1266. }
  1267. if( m_pDigestContextCache != NULL )
  1268. {
  1269. delete m_pDigestContextCache;
  1270. m_pDigestContextCache = NULL;
  1271. }
  1272. if ( m_pUrlInfoCache != NULL )
  1273. {
  1274. delete m_pUrlInfoCache;
  1275. m_pUrlInfoCache = NULL;
  1276. }
  1277. if ( m_pUlCache != NULL )
  1278. {
  1279. delete m_pUlCache;
  1280. m_pUlCache = NULL;
  1281. }
  1282. return hr;
  1283. }
  1284. HRESULT
  1285. W3_SERVER::HandleMetabaseChange(
  1286. const MD_CHANGE_OBJECT & ChangeObject
  1287. )
  1288. /*++
  1289. Routine Description:
  1290. Handle change notifications from the metabase.
  1291. The change object will contain a change to
  1292. /LM/W3SVC/ or lower in the metabase tree.
  1293. Changes to /LM/W3SVC/ may alter W3_SERVER and
  1294. are passed to all sites in the site list.
  1295. Changes to /LM/W3SVC/{site id}/ or lower will
  1296. affect only one site so are just passed on.
  1297. Arguments:
  1298. ChangeObject
  1299. Return Value:
  1300. CODEWORK - Partial implementation 1/26/00 - TaylorW
  1301. --*/
  1302. {
  1303. DBGPRINTF(( DBG_CONTEXT,
  1304. "W3_SERVER Notfied - Path(%S) Type(%d) NumIds(%08x)\n",
  1305. ChangeObject.pszMDPath,
  1306. ChangeObject.dwMDChangeType,
  1307. ChangeObject.dwMDNumDataIDs
  1308. ));
  1309. HRESULT hr = NOERROR;
  1310. BOOL IsPathW3 = FALSE;
  1311. BOOL IsPathSite = FALSE;
  1312. //
  1313. // Find the instance id if present
  1314. //
  1315. DWORD SiteId;
  1316. LPWSTR SiteIdString = ChangeObject.pszMDPath + W3_SERVER_MB_PATH_CCH;
  1317. LPWSTR StringEnd;
  1318. if( SiteIdString[0] == L'\0' )
  1319. {
  1320. IsPathW3 = TRUE;
  1321. }
  1322. else
  1323. {
  1324. SiteId = wcstoul( SiteIdString, &StringEnd, 10 );
  1325. if( SiteId != 0 )
  1326. {
  1327. IsPathSite = TRUE;
  1328. }
  1329. }
  1330. W3_SITE * Site = NULL;
  1331. if( IsPathSite )
  1332. {
  1333. //
  1334. // We just need to notify a specific site
  1335. //
  1336. DBG_ASSERT( SiteId );
  1337. Site = FindSite(SiteId);
  1338. if (Site != NULL)
  1339. {
  1340. hr = Site->HandleMetabaseChange( ChangeObject );
  1341. Site->DereferenceSite();
  1342. }
  1343. }
  1344. else if( IsPathW3 )
  1345. {
  1346. //
  1347. // We need to notify every site
  1348. //
  1349. m_pSiteList->WriteLock();
  1350. W3_SITE_LIST TempSiteList;
  1351. for (W3_SITE_LIST::iterator iter = m_pSiteList->begin();
  1352. iter != m_pSiteList->end();
  1353. ++iter)
  1354. {
  1355. Site = iter.Record();
  1356. Site->HandleMetabaseChange( ChangeObject, &TempSiteList );
  1357. }
  1358. m_pSiteList->Clear();
  1359. m_cSites = 0;
  1360. for (W3_SITE_LIST::iterator iter = TempSiteList.begin();
  1361. iter != TempSiteList.end();
  1362. ++iter)
  1363. {
  1364. Site = iter.Record();
  1365. AddSite(Site);
  1366. }
  1367. m_pSiteList->WriteUnlock();
  1368. //
  1369. // Handle changes to this object's data
  1370. //
  1371. // At this point all we care about is data changes
  1372. //
  1373. if( (ChangeObject.dwMDChangeType & MD_CHANGE_TYPE_DELETE_DATA) ||
  1374. (ChangeObject.dwMDChangeType & MD_CHANGE_TYPE_SET_DATA) )
  1375. {
  1376. DWORD n;
  1377. for ( n = 0; n < ChangeObject.dwMDNumDataIDs; n++ )
  1378. {
  1379. if ( ChangeObject.pdwMDDataIDs[n] == MD_WEB_SVC_EXT_RESTRICTION_LIST )
  1380. {
  1381. hr = InitializeRestrictionList( IsapiRestrictionList );
  1382. if ( FAILED( hr ) )
  1383. {
  1384. DBGPRINTF(( DBG_CONTEXT,
  1385. "Failed to initialize IsapiRestrictionList "
  1386. "on a metabase change. Error 0x%08x.\r\n",
  1387. hr ));
  1388. }
  1389. hr = InitializeRestrictionList( CgiRestrictionList );
  1390. if ( FAILED( hr ) )
  1391. {
  1392. DBGPRINTF(( DBG_CONTEXT,
  1393. "Failed to initialize CgiRestrictionList "
  1394. "on a metabase change. Error 0x%08x.\r\n",
  1395. hr ));
  1396. }
  1397. }
  1398. }
  1399. }
  1400. }
  1401. return S_OK;
  1402. }
  1403. //static
  1404. VOID
  1405. W3_SERVER::OnShutdown(
  1406. BOOL fDoImmediate
  1407. )
  1408. /*++
  1409. Routine Description:
  1410. Called right after IPM indication of shutdown (but before drain)
  1411. Arguments:
  1412. None
  1413. Return Value:
  1414. None
  1415. --*/
  1416. {
  1417. if (g_pW3Server->m_fInBackwardCompatibilityMode)
  1418. {
  1419. RAW_CONNECTION::StopListening();
  1420. }
  1421. if (fDoImmediate)
  1422. {
  1423. W3_CGI_HANDLER::KillAllCgis();
  1424. }
  1425. }
  1426. HRESULT W3_SERVER::CollectCounters(PBYTE *ppCounterData,
  1427. DWORD *pdwCounterData)
  1428. {
  1429. //
  1430. // Initialize to null
  1431. //
  1432. *ppCounterData = NULL;
  1433. *pdwCounterData = 0;
  1434. //
  1435. // Make sure we have enough memory
  1436. //
  1437. DWORD dwCounterBufferNeeded = sizeof(IISWPSiteCounters) * m_cSites +
  1438. sizeof(IISWPGlobalCounters) + sizeof(ULONGLONG);
  1439. if (m_pCounterDataBuffer == NULL)
  1440. {
  1441. m_pCounterDataBuffer = (PBYTE)LocalAlloc(LMEM_FIXED, dwCounterBufferNeeded);
  1442. if (m_pCounterDataBuffer == NULL)
  1443. {
  1444. return HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
  1445. }
  1446. m_dwCounterDataBuffer = dwCounterBufferNeeded;
  1447. }
  1448. else if (m_dwCounterDataBuffer < dwCounterBufferNeeded)
  1449. {
  1450. BYTE *pCounterDataBuffer = (PBYTE)LocalReAlloc(m_pCounterDataBuffer,
  1451. dwCounterBufferNeeded,
  1452. LMEM_MOVEABLE);
  1453. if (pCounterDataBuffer == NULL)
  1454. {
  1455. return HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
  1456. }
  1457. m_pCounterDataBuffer = pCounterDataBuffer;
  1458. m_dwCounterDataBuffer = dwCounterBufferNeeded;
  1459. }
  1460. m_pSiteList->ReadLock();
  1461. //
  1462. // Get the Site counters
  1463. //
  1464. DWORD i = 0;
  1465. for (W3_SITE_LIST::iterator iter = m_pSiteList->begin();
  1466. iter != m_pSiteList->end();
  1467. ++iter, ++i)
  1468. {
  1469. //
  1470. // In case some more new sites got added in between, skip them for now
  1471. //
  1472. if ((i+1)*sizeof(IISWPSiteCounters) + sizeof(IISWPGlobalCounters) >=
  1473. m_dwCounterDataBuffer)
  1474. {
  1475. break;
  1476. }
  1477. W3_SITE *pSite = iter.Record();
  1478. pSite->GetStatistics((IISWPSiteCounters *)
  1479. (m_pCounterDataBuffer +
  1480. i*sizeof(IISWPSiteCounters) + sizeof(DWORD)));
  1481. }
  1482. m_pSiteList->ReadUnlock();
  1483. //
  1484. // Set the number of sites
  1485. //
  1486. *(DWORD *)m_pCounterDataBuffer = i;
  1487. //
  1488. // Get the Global counters
  1489. //
  1490. IISWPGlobalCounters *pCacheCtrs = (IISWPGlobalCounters *)
  1491. (m_pCounterDataBuffer + i*sizeof(IISWPSiteCounters) + sizeof(DWORD));
  1492. //
  1493. // This contains some ULONGLONG values so align it, this is how WAS
  1494. // expects it
  1495. //
  1496. pCacheCtrs = (IISWPGlobalCounters *)(((DWORD_PTR)pCacheCtrs + 7) & ~7);
  1497. GetCacheStatistics(pCacheCtrs);
  1498. *ppCounterData = m_pCounterDataBuffer;
  1499. *pdwCounterData = (DWORD)DIFF((LPBYTE)pCacheCtrs - m_pCounterDataBuffer) + sizeof(IISWPGlobalCounters);
  1500. return S_OK;
  1501. }
  1502. VOID
  1503. W3_SERVER::GetCacheStatistics(
  1504. IISWPGlobalCounters * pCacheCtrs
  1505. )
  1506. /*++
  1507. Routine Description:
  1508. Get cache statistics for perfmon purposes
  1509. Arguments:
  1510. pCacheCtrs - Receives the statistics for cache
  1511. Notes:
  1512. CacheBytesTotal and CacheBytesInUse are not kept on a per-server basis
  1513. so they are only returned when retrieving summary statistics.
  1514. Returns:
  1515. None
  1516. --*/
  1517. {
  1518. //
  1519. // Get file cache statistics
  1520. //
  1521. if ( m_pFileCache != NULL )
  1522. {
  1523. pCacheCtrs->CurrentFilesCached = m_pFileCache->PerfQueryCurrentEntryCount();
  1524. pCacheCtrs->TotalFilesCached = m_pFileCache->PerfQueryTotalEntriesCached();
  1525. pCacheCtrs->FileCacheHits = m_pFileCache->PerfQueryHits();
  1526. pCacheCtrs->FileCacheMisses = m_pFileCache->PerfQueryMisses();
  1527. pCacheCtrs->FileCacheFlushes = m_pFileCache->PerfQueryFlushCalls();
  1528. pCacheCtrs->ActiveFlushedFiles = m_pFileCache->PerfQueryActiveFlushedEntries();
  1529. pCacheCtrs->TotalFlushedFiles = m_pFileCache->PerfQueryFlushes();
  1530. pCacheCtrs->CurrentFileCacheMemoryUsage = m_pFileCache->PerfQueryCurrentMemCacheSize();
  1531. pCacheCtrs->MaxFileCacheMemoryUsage = m_pFileCache->PerfQueryMaxMemCacheSize();
  1532. }
  1533. //
  1534. // Get URI cache statistics
  1535. //
  1536. if ( m_pUrlInfoCache != NULL )
  1537. {
  1538. pCacheCtrs->CurrentUrisCached = m_pUrlInfoCache->PerfQueryCurrentEntryCount();
  1539. pCacheCtrs->TotalUrisCached = m_pUrlInfoCache->PerfQueryTotalEntriesCached();
  1540. pCacheCtrs->UriCacheHits = m_pUrlInfoCache->PerfQueryHits();
  1541. pCacheCtrs->UriCacheMisses = m_pUrlInfoCache->PerfQueryMisses();
  1542. pCacheCtrs->UriCacheFlushes = m_pUrlInfoCache->PerfQueryFlushCalls();
  1543. pCacheCtrs->TotalFlushedUris = m_pUrlInfoCache->PerfQueryFlushes();
  1544. }
  1545. //
  1546. // BLOB cache counters (actually since there is no blob cache we will
  1547. // sub in the metacache counters which are more interesting since
  1548. // metacache misses are really painful
  1549. //
  1550. if ( m_pMetaCache != NULL )
  1551. {
  1552. pCacheCtrs->CurrentBlobsCached = m_pMetaCache->PerfQueryCurrentEntryCount();
  1553. pCacheCtrs->TotalBlobsCached = m_pMetaCache->PerfQueryTotalEntriesCached();
  1554. pCacheCtrs->BlobCacheHits = m_pMetaCache->PerfQueryHits();
  1555. pCacheCtrs->BlobCacheMisses = m_pMetaCache->PerfQueryMisses();
  1556. pCacheCtrs->BlobCacheFlushes = m_pMetaCache->PerfQueryFlushCalls();
  1557. pCacheCtrs->TotalFlushedBlobs = m_pMetaCache->PerfQueryFlushes();
  1558. }
  1559. }
  1560. HRESULT
  1561. W3_SERVER::ReadUseDigestSSP(
  1562. VOID
  1563. )
  1564. /*++
  1565. Routine description:
  1566. Read the UseDigestSSP property from the metabase
  1567. Arguments:
  1568. none
  1569. Return Value:
  1570. HRESULT
  1571. --*/
  1572. {
  1573. MB mb( QueryMDObject() );
  1574. if ( !mb.Open( QueryMDPath() ) )
  1575. {
  1576. return HRESULT_FROM_WIN32(GetLastError());
  1577. }
  1578. if ( !mb.GetDword( L"",
  1579. MD_USE_DIGEST_SSP,
  1580. IIS_MD_UT_SERVER,
  1581. ( DWORD * )&m_fUseDigestSSP,
  1582. 0 ) )
  1583. {
  1584. m_fUseDigestSSP = TRUE;
  1585. }
  1586. mb.Close();
  1587. return S_OK;
  1588. }
  1589. HRESULT
  1590. W3_SERVER::InitializeRestrictionList(
  1591. RESTRICTION_LIST_TYPE ListType
  1592. )
  1593. {
  1594. W3_RESTRICTION_LIST * pNewRestrictionList = NULL;
  1595. MULTISZ msz;
  1596. BOOL fResult;
  1597. DBG_ASSERT( m_pMetaBase );
  1598. DBG_ASSERT( ListType == IsapiRestrictionList ||
  1599. ListType == CgiRestrictionList );
  1600. //
  1601. // Get the metadata
  1602. //
  1603. MB mb( m_pMetaBase );
  1604. if ( !mb.Open( L"/LM/W3SVC/" ) )
  1605. {
  1606. return HRESULT_FROM_WIN32( GetLastError() );
  1607. }
  1608. fResult = mb.GetMultisz( L"",
  1609. MD_WEB_SVC_EXT_RESTRICTION_LIST,
  1610. IIS_MD_UT_SERVER,
  1611. &msz );
  1612. if ( !fResult )
  1613. {
  1614. //
  1615. // If we fail to get the metadata, use default data
  1616. //
  1617. msz.Reset();
  1618. fResult = msz.Append( L"0,*.dll" );
  1619. if ( fResult )
  1620. {
  1621. fResult = msz.Append( L"0,*.exe" );
  1622. }
  1623. }
  1624. mb.Close();
  1625. if ( !fResult )
  1626. {
  1627. return HRESULT_FROM_WIN32( GetLastError() );
  1628. }
  1629. //
  1630. // Create the new list
  1631. //
  1632. pNewRestrictionList = CreateRestrictionList( &msz,
  1633. ListType );
  1634. if ( pNewRestrictionList == NULL )
  1635. {
  1636. return HRESULT_FROM_WIN32( GetLastError() );
  1637. }
  1638. //
  1639. // Swap in the new list
  1640. //
  1641. if ( ListType == IsapiRestrictionList )
  1642. {
  1643. m_IsapiRestrictionLock.WriteLock();
  1644. //
  1645. // Release the old list and put in the new one
  1646. //
  1647. if ( m_pIsapiRestrictionList != NULL )
  1648. {
  1649. m_pIsapiRestrictionList->DereferenceRestrictionList();
  1650. }
  1651. m_pIsapiRestrictionList = pNewRestrictionList;
  1652. m_fDavEnabled = pNewRestrictionList->IsImageEnabled(W3_DAV_HANDLER::QueryDavImage());
  1653. m_IsapiRestrictionLock.WriteUnlock();
  1654. }
  1655. else
  1656. {
  1657. m_CgiRestrictionLock.WriteLock();
  1658. //
  1659. // Release the old list and put in the new one
  1660. //
  1661. if ( m_pCgiRestrictionList != NULL )
  1662. {
  1663. m_pCgiRestrictionList->DereferenceRestrictionList();
  1664. }
  1665. m_pCgiRestrictionList = pNewRestrictionList;
  1666. m_CgiRestrictionLock.WriteUnlock();
  1667. }
  1668. return NOERROR;
  1669. }
  1670. W3_RESTRICTION_LIST *
  1671. W3_SERVER::CreateRestrictionList(
  1672. MULTISZ * pmszImageList,
  1673. RESTRICTION_LIST_TYPE ListType
  1674. )
  1675. {
  1676. W3_RESTRICTION_LIST * pNewRestrictionList;
  1677. DWORD dwNumStrings;
  1678. HRESULT hr = NOERROR;
  1679. DBG_ASSERT( pmszImageList );
  1680. //
  1681. // Get the string count
  1682. //
  1683. dwNumStrings = pmszImageList->QueryStringCount();
  1684. if ( dwNumStrings == 0 )
  1685. {
  1686. SetLastError( ERROR_INVALID_PARAMETER );
  1687. return NULL;
  1688. }
  1689. //
  1690. // Allocate a new restriction list object
  1691. //
  1692. pNewRestrictionList = new W3_RESTRICTION_LIST;
  1693. if ( pNewRestrictionList == NULL )
  1694. {
  1695. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  1696. return NULL;
  1697. }
  1698. //
  1699. // Initialize it and return the result
  1700. //
  1701. hr = pNewRestrictionList->Create( pmszImageList,
  1702. ListType );
  1703. if ( FAILED( hr ) )
  1704. {
  1705. pNewRestrictionList->DereferenceRestrictionList();
  1706. pNewRestrictionList = NULL;
  1707. SetLastError( WIN32_FROM_HRESULT( hr ) );
  1708. return NULL;
  1709. }
  1710. return pNewRestrictionList;
  1711. }
  1712. BOOL
  1713. W3_SERVER::QueryIsIsapiImageEnabled(
  1714. LPCWSTR szImage
  1715. )
  1716. {
  1717. W3_RESTRICTION_LIST * pRestrictionList;
  1718. BOOL fRet;
  1719. //
  1720. // Acquire a read lock on the IsapiRestrictionList so
  1721. // that we can AddRef it without fear of a metabase
  1722. // update invalidating it first.
  1723. //
  1724. m_IsapiRestrictionLock.ReadLock();
  1725. pRestrictionList = m_pIsapiRestrictionList;
  1726. DBG_ASSERT( pRestrictionList );
  1727. pRestrictionList->ReferenceRestrictionList();
  1728. m_IsapiRestrictionLock.ReadUnlock();
  1729. fRet = pRestrictionList->IsImageEnabled( szImage );
  1730. pRestrictionList->DereferenceRestrictionList();
  1731. pRestrictionList = NULL;
  1732. return fRet;
  1733. }
  1734. BOOL
  1735. W3_SERVER::QueryIsCgiImageEnabled(
  1736. LPCWSTR szImage
  1737. )
  1738. {
  1739. W3_RESTRICTION_LIST * pRestrictionList;
  1740. BOOL fRet;
  1741. //
  1742. // Acquire a read lock on the IsapiRestrictionList so
  1743. // that we can AddRef it without fear of a metabase
  1744. // update invalidating it first.
  1745. //
  1746. m_CgiRestrictionLock.ReadLock();
  1747. pRestrictionList = m_pCgiRestrictionList;
  1748. DBG_ASSERT( pRestrictionList );
  1749. pRestrictionList->ReferenceRestrictionList();
  1750. m_CgiRestrictionLock.ReadUnlock();
  1751. fRet = pRestrictionList->IsImageEnabled( szImage );
  1752. pRestrictionList->DereferenceRestrictionList();
  1753. pRestrictionList = NULL;
  1754. return fRet;
  1755. }