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.

3654 lines
90 KiB

  1. /*++
  2. Copyright (c) 1998 Microsoft Corporation
  3. Module Name :
  4. ulcontext.cxx
  5. Abstract:
  6. Implementation of FILTER_CHANNEL_CONTEXT. One such object for every connection
  7. Environment:
  8. Win32 - User Mode
  9. Project:
  10. Stream Filter Worker Process
  11. --*/
  12. #include "precomp.hxx"
  13. #ifndef MAXDWORD
  14. #define MAXDWORD 0xFFFFFFFFul
  15. #endif
  16. //static
  17. ALLOC_CACHE_HANDLER *
  18. SSL_SERVER_FILTER_CHANNEL_CONTEXT::sm_pachFilterChannelContexts = NULL;
  19. //static
  20. ALLOC_CACHE_HANDLER *
  21. UL_OVERLAPPED_CONTEXT::sm_pachUlOverlappedContexts = NULL;
  22. //static
  23. ALLOC_CACHE_HANDLER *
  24. UL_OVERLAPPED_CONTEXT::sm_pachRawWriteBuffers = NULL;
  25. //static
  26. ALLOC_CACHE_HANDLER *
  27. UL_OVERLAPPED_CONTEXT::sm_pachRawReadBuffers = NULL;
  28. //static
  29. ALLOC_CACHE_HANDLER *
  30. UL_OVERLAPPED_CONTEXT::sm_pachAppReadBuffers = NULL;
  31. //static
  32. DWORD
  33. FILTER_CHANNEL::sm_dwDefaultRawReadSize = DEFAULT_RAW_READ_SIZE ;
  34. //static
  35. DWORD
  36. FILTER_CHANNEL::sm_dwDefaultAppReadSize = DEFAULT_APP_READ_SIZE;
  37. //static
  38. DWORD
  39. FILTER_CHANNEL::sm_dwContextDesiredOutstanding = UL_CONTEXT_DESIRED_OUTSTANDING;
  40. //static
  41. BOOL
  42. FILTER_CHANNEL::sm_fEnableTemporaryBuffers = TRUE;
  43. //static
  44. DWORD
  45. FILTER_CHANNEL::sm_dwHandshakeTimeoutInSec = DEFAULT_RENEGOTIATION_TIMEOUT_IN_SEC;
  46. UL_OVERLAPPED_CONTEXT::UL_OVERLAPPED_CONTEXT(
  47. UL_OVERLAPPED_CONTEXT_TYPE type,
  48. UL_OVERLAPPED_CONTEXT_SUBTYPE subtype
  49. )
  50. {
  51. _type = type;
  52. _subtype = subtype;
  53. _pCallback = NULL;
  54. _pCallbackParam = NULL;
  55. ZeroMemory( &_Overlapped, sizeof(_Overlapped) );
  56. // internal Data buffer related initialization
  57. _pbData = NULL;
  58. _cbData = 0;
  59. _fDynAllocated = FALSE;
  60. switch ( QueryType() )
  61. {
  62. case UL_OVERLAPPED_CONTEXT_RAW_READ:
  63. _pCurrentACache = sm_pachRawReadBuffers;
  64. _cbCurrentACacheElementSize =
  65. FILTER_CHANNEL::QueryDefaultRawReadSize();
  66. break;
  67. case UL_OVERLAPPED_CONTEXT_RAW_WRITE:
  68. _pCurrentACache = sm_pachRawWriteBuffers;
  69. _cbCurrentACacheElementSize =
  70. FILTER_CHANNEL::QueryDefaultRawWriteSize();
  71. break;
  72. case UL_OVERLAPPED_CONTEXT_APP_READ:
  73. _pCurrentACache = sm_pachAppReadBuffers;
  74. _cbCurrentACacheElementSize =
  75. FILTER_CHANNEL::QueryDefaultAppReadSize();
  76. break;
  77. case UL_OVERLAPPED_CONTEXT_APP_WRITE:
  78. default:
  79. _pCurrentACache = NULL;
  80. _cbCurrentACacheElementSize = 0;
  81. break;
  82. }
  83. }
  84. //static
  85. HRESULT
  86. UL_OVERLAPPED_CONTEXT::Initialize(
  87. VOID
  88. )
  89. /*++
  90. Routine Description:
  91. Global initialization routine for UL_OVERLAPPED_CONTEXT
  92. Arguments:
  93. None
  94. Return Value:
  95. HRESULT
  96. --*/
  97. {
  98. ALLOC_CACHE_CONFIGURATION acConfig;
  99. //
  100. // Setup allocation lookaside
  101. //
  102. acConfig.nConcurrency = 1;
  103. acConfig.nThreshold = 100;
  104. // UL_OVERLAPPED_CONTEXT ACACHE
  105. acConfig.cbSize = sizeof( UL_OVERLAPPED_CONTEXT );
  106. DBG_ASSERT( sm_pachUlOverlappedContexts == NULL );
  107. sm_pachUlOverlappedContexts = new ALLOC_CACHE_HANDLER( "UL_OVERLAPPED_CONTEXT",
  108. &acConfig );
  109. if ( sm_pachUlOverlappedContexts == NULL )
  110. {
  111. return HRESULT_FROM_WIN32( ERROR_NOT_ENOUGH_MEMORY );
  112. }
  113. // Raw Write Buffers ACACHE
  114. acConfig.cbSize =
  115. FILTER_CHANNEL::QueryDefaultRawWriteSize();
  116. DBG_ASSERT( sm_pachRawWriteBuffers == NULL );
  117. sm_pachRawWriteBuffers = new ALLOC_CACHE_HANDLER( "RAW_WRITE_BUFFERS",
  118. &acConfig );
  119. if ( sm_pachRawWriteBuffers == NULL )
  120. {
  121. return HRESULT_FROM_WIN32( ERROR_NOT_ENOUGH_MEMORY );
  122. }
  123. // Raw Read Buffers ACACHE
  124. acConfig.cbSize =
  125. FILTER_CHANNEL::QueryDefaultRawReadSize();
  126. DBG_ASSERT( sm_pachRawReadBuffers == NULL );
  127. sm_pachRawReadBuffers = new ALLOC_CACHE_HANDLER( "RAW_READ_BUFFERS",
  128. &acConfig );
  129. if ( sm_pachRawReadBuffers == NULL )
  130. {
  131. return HRESULT_FROM_WIN32( ERROR_NOT_ENOUGH_MEMORY );
  132. }
  133. // App Read Buffers ACACHE
  134. acConfig.cbSize =
  135. FILTER_CHANNEL::QueryDefaultAppReadSize();
  136. DBG_ASSERT( sm_pachAppReadBuffers == NULL );
  137. sm_pachAppReadBuffers = new ALLOC_CACHE_HANDLER( "APP_READ_BUFFERS",
  138. &acConfig );
  139. if ( sm_pachAppReadBuffers == NULL )
  140. {
  141. return HRESULT_FROM_WIN32( ERROR_NOT_ENOUGH_MEMORY );
  142. }
  143. return NO_ERROR;
  144. }
  145. //static
  146. VOID
  147. UL_OVERLAPPED_CONTEXT::Terminate(
  148. VOID
  149. )
  150. /*++
  151. Routine Description:
  152. Terminate UL_OVERLAPPED_CONTEXT globals
  153. Arguments:
  154. None
  155. Return Value:
  156. None
  157. --*/
  158. {
  159. if ( sm_pachAppReadBuffers != NULL )
  160. {
  161. delete sm_pachAppReadBuffers;
  162. sm_pachAppReadBuffers = NULL;
  163. }
  164. if ( sm_pachRawReadBuffers != NULL )
  165. {
  166. delete sm_pachRawReadBuffers;
  167. sm_pachRawReadBuffers = NULL;
  168. }
  169. if ( sm_pachRawWriteBuffers != NULL )
  170. {
  171. delete sm_pachRawWriteBuffers;
  172. sm_pachRawWriteBuffers = NULL;
  173. }
  174. if ( sm_pachUlOverlappedContexts != NULL )
  175. {
  176. delete sm_pachUlOverlappedContexts;
  177. sm_pachUlOverlappedContexts = NULL;
  178. }
  179. }
  180. BOOL
  181. UL_OVERLAPPED_CONTEXT::ResizeDataBuffer(
  182. DWORD cbNewSize
  183. )
  184. /*++
  185. Routine Description:
  186. Resize internal data buffer
  187. - if requested size fits within the range of the
  188. ACACHE entry size then ACACHEd entry is returned
  189. Otherwise heap allocation is made.
  190. Content of the previous buffer is copied to the new one
  191. Arguments:
  192. None
  193. Return Value:
  194. BOOL (this is just to follow the legacy of the BUFFER type that
  195. was used previously)
  196. --*/
  197. {
  198. if ( _cbData >= cbNewSize )
  199. {
  200. return TRUE;
  201. }
  202. PBYTE pbPrevData = _pbData;
  203. DWORD cbPrevData = _cbData;
  204. BOOL fPrevDynAllocated = _fDynAllocated;
  205. if ( _cbCurrentACacheElementSize >= cbNewSize &&
  206. _pCurrentACache != NULL )
  207. {
  208. //
  209. // use ACACHE
  210. //
  211. _pbData = (PBYTE) _pCurrentACache->Alloc();
  212. if ( _pbData != NULL )
  213. {
  214. _cbData = _cbCurrentACacheElementSize;
  215. _fDynAllocated = FALSE;
  216. }
  217. }
  218. else
  219. {
  220. //
  221. // Requested size was too big for ACACHE
  222. // We have to allocate on the heap
  223. // round up the allocation unit to minimize access to the heap
  224. //
  225. DWORD cbAllocIncrement = 4096;
  226. DWORD cbNewAllocSize = cbAllocIncrement *
  227. ( ( cbNewSize / cbAllocIncrement ) + 1 );
  228. _pbData = new BYTE[ cbNewAllocSize ];
  229. if (_pbData != NULL )
  230. {
  231. _cbData = cbNewAllocSize;
  232. _fDynAllocated = TRUE;
  233. }
  234. }
  235. if ( _pbData == NULL )
  236. {
  237. _pbData = pbPrevData;
  238. _cbData = cbPrevData;
  239. _fDynAllocated = fPrevDynAllocated;
  240. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  241. return FALSE;
  242. }
  243. //
  244. // Copy previous content if necessary
  245. //
  246. if ( cbPrevData != 0 && pbPrevData != NULL )
  247. {
  248. memcpy( _pbData, pbPrevData, cbPrevData );
  249. }
  250. if ( pbPrevData != NULL )
  251. {
  252. if ( fPrevDynAllocated )
  253. {
  254. delete [] pbPrevData;
  255. }
  256. else
  257. {
  258. _pCurrentACache->Free( pbPrevData );
  259. }
  260. }
  261. return TRUE;
  262. }
  263. VOID
  264. UL_OVERLAPPED_CONTEXT::FreeDataBuffer(
  265. VOID
  266. )
  267. /*++
  268. Routine Description:
  269. free the internal data buffer's memory
  270. Arguments:
  271. None
  272. Return Value:
  273. none
  274. --*/
  275. {
  276. if ( _pbData == NULL )
  277. {
  278. return;
  279. }
  280. if ( _fDynAllocated )
  281. {
  282. delete [] _pbData;
  283. }
  284. else
  285. {
  286. _pCurrentACache->Free( _pbData );
  287. }
  288. _pbData = NULL;
  289. _cbData = 0;
  290. }
  291. FILTER_CHANNEL_CONTEXT::FILTER_CHANNEL_CONTEXT(
  292. FILTER_CHANNEL *pManager
  293. )
  294. : _RawWriteData1Overlapped( UL_OVERLAPPED_CONTEXT_RAW_WRITE,
  295. UL_OVERLAPPED_CONTEXT_DATA ),
  296. _RawWriteData2Overlapped( UL_OVERLAPPED_CONTEXT_RAW_WRITE,
  297. UL_OVERLAPPED_CONTEXT_DATA ),
  298. _RawReadOverlapped( UL_OVERLAPPED_CONTEXT_RAW_READ ),
  299. _AppWriteOverlapped( UL_OVERLAPPED_CONTEXT_APP_WRITE ),
  300. _AppReadOverlapped( UL_OVERLAPPED_CONTEXT_APP_READ ),
  301. _CloseOverlapped( UL_OVERLAPPED_CONTEXT_CLOSE ),
  302. _buffConnectionInfo( _abConnectionInfo, sizeof( _abConnectionInfo ) ),
  303. _fCloseConnection( FALSE ),
  304. _cRefs( 1 ),
  305. _cbRawReadData( 0 ),
  306. _fNewConnection( TRUE ),
  307. _pSSLContext( NULL ),
  308. _lQueuedAppReads( 0 ),
  309. _fAppReadInProgress( FALSE ),
  310. _pISAPIContext( NULL ),
  311. _cbNextRawReadSize( FILTER_CHANNEL::QueryDefaultRawReadSize() ),
  312. _ulFilterBufferType( (HTTP_FILTER_BUFFER_TYPE) -1 ),
  313. _pManager( pManager ),
  314. _pEndpointConfig( NULL ),
  315. _pLastAcquiredRawWriteOverlapped( NULL ),
  316. _fTimerTickCountSet( FALSE )
  317. {
  318. _RawWriteData1Overlapped.SetContext( this );
  319. _RawWriteData2Overlapped.SetContext( this );
  320. _RawReadOverlapped.SetContext( this );
  321. _AppWriteOverlapped.SetContext( this );
  322. _AppReadOverlapped.SetContext( this );
  323. _CloseOverlapped.SetContext( this ),
  324. _RawWriteOverlappedFreeList.Next = NULL;
  325. PushEntryList( &_RawWriteOverlappedFreeList, _RawWriteData1Overlapped.QueryListEntry() );
  326. PushEntryList( &_RawWriteOverlappedFreeList, _RawWriteData2Overlapped.QueryListEntry() );
  327. _dwLockIndex = 0;
  328. _pManager->InsertFiltChannelContext(this);
  329. _pConnectionInfo = (HTTP_RAW_CONNECTION_INFO*) _buffConnectionInfo.QueryPtr();
  330. _pConnectionInfo->pInitialData = (PBYTE)_pConnectionInfo +
  331. sizeof(HTTP_RAW_CONNECTION_INFO);
  332. _pConnectionInfo->InitialDataSize = _buffConnectionInfo.QuerySize() -
  333. sizeof(HTTP_RAW_CONNECTION_INFO);
  334. // signature will be added by inheriting class
  335. }
  336. FILTER_CHANNEL_CONTEXT::~FILTER_CHANNEL_CONTEXT()
  337. {
  338. //
  339. // Cleanup any attached stream context
  340. //
  341. if ( _pISAPIContext != NULL )
  342. {
  343. delete _pISAPIContext;
  344. _pISAPIContext = NULL;
  345. }
  346. if ( _pSSLContext != NULL )
  347. {
  348. delete _pSSLContext;
  349. _pSSLContext = NULL;
  350. }
  351. if ( _pEndpointConfig != NULL )
  352. {
  353. _pEndpointConfig->DereferenceEndpointConfig();
  354. _pEndpointConfig = NULL;
  355. }
  356. //
  357. // Manage the list of active UL_CONTEXTs
  358. //
  359. _pManager->RemoveFiltChannelContext(this);
  360. }
  361. VOID
  362. FILTER_CHANNEL_CONTEXT::ReferenceFiltChannelContext(
  363. VOID
  364. )
  365. /*++
  366. Routine Description:
  367. Reference the FILTER_CHANNEL_CONTEXT
  368. Arguments:
  369. none
  370. Return Value:
  371. none
  372. --*/
  373. {
  374. LONG cRefs;
  375. cRefs = InterlockedIncrement( &_cRefs );
  376. #if DBG
  377. //
  378. // Log the reference ( sm_pTraceLog!=NULL if DBG=1)
  379. //
  380. _pManager->WriteRefTraceLog( cRefs,
  381. this );
  382. #endif
  383. }
  384. VOID
  385. FILTER_CHANNEL_CONTEXT::DereferenceFiltChannelContext(
  386. VOID
  387. )
  388. /*++
  389. Routine Description:
  390. Dereference (and possible destroy) the FILTER_CHANNEL_CONTEXT
  391. Arguments:
  392. none
  393. Return Value:
  394. none
  395. --*/
  396. {
  397. LONG cRefs;
  398. #if DBG
  399. //
  400. // We have to store pManager before Decrementing reference
  401. // because after dereferencing it's illegal to access the data
  402. // of the class because there is no guarantee that the instance
  403. // still exists. Also it's necessary to guarantee that
  404. // pManager will not be deleted before any thread executing
  405. // this code is completed
  406. // (Threadpool must be destroyed first - see the Terminate() call)
  407. //
  408. FILTER_CHANNEL * pManager = _pManager;
  409. #endif
  410. cRefs = InterlockedDecrement( &_cRefs );
  411. #if DBG
  412. pManager->WriteRefTraceLog( cRefs,
  413. this );
  414. #endif
  415. if ( cRefs == 0 )
  416. {
  417. //
  418. // CONTEXT is to be destroyed
  419. // Remove it from the timer list so that there are
  420. // are only valid entries on the list
  421. //
  422. StopTimeoutTimer();
  423. delete this;
  424. }
  425. }
  426. HRESULT
  427. FILTER_CHANNEL_CONTEXT::OnAppReadCompletion(
  428. DWORD /*cbCompletion*/,
  429. DWORD dwCompletionStatus
  430. )
  431. /*++
  432. Routine Description:
  433. Completion for reads from an application
  434. Arguments:
  435. cbCompletion - Bytes of completion (currently not used)
  436. dwCompletionStatus - Completion error
  437. Return Value:
  438. HRESULT
  439. --*/
  440. {
  441. HTTP_FILTER_BUFFER * pFilterBuffer;
  442. HRESULT hr = E_FAIL;
  443. RAW_STREAM_INFO rawStreamInfo;
  444. BOOL fComplete = FALSE;
  445. BOOL fPostAppRead = FALSE;
  446. //
  447. // Just bail on errors
  448. //
  449. if ( dwCompletionStatus != NO_ERROR )
  450. {
  451. hr = HRESULT_FROM_WIN32( dwCompletionStatus );
  452. goto ExitPoint;
  453. }
  454. pFilterBuffer = (HTTP_FILTER_BUFFER *) _ulAppReadFilterBuffer.pBuffer;
  455. _ulFilterBufferType = pFilterBuffer->BufferType;
  456. DBG_ASSERT( !_fNewConnection );
  457. //
  458. // If HTTP.SYS is telling us to close the connection, then do so now
  459. //
  460. if ( _ulFilterBufferType == HttpFilterBufferCloseConnection )
  461. {
  462. //
  463. // Connection is to be closed gracefully
  464. // One outstanding overlapped Raw Write may exists.
  465. // Since HTTP.SYS will perform
  466. // graceful disconnect it is safe to call StartClose() right now
  467. // and no data from the outstanding RawWrite will be lost.
  468. // Also the delayed ACK problem on the last send will not apply if close
  469. // is requested while one RawWrite may still be outstanding
  470. //
  471. StartClose();
  472. hr = S_OK;
  473. goto ExitPoint;
  474. }
  475. //
  476. // Setup raw stream descriptor
  477. //
  478. rawStreamInfo.pbBuffer = (PBYTE) pFilterBuffer->pBuffer;
  479. rawStreamInfo.cbBuffer = pFilterBuffer->BufferSize;
  480. rawStreamInfo.cbData = pFilterBuffer->BufferSize;
  481. //
  482. // First notify ISAPI filters if this is a stream from the application
  483. // if _pISAPIContext is null then notification is disabled
  484. if ( _ulFilterBufferType == HttpFilterBufferHttpStream &&
  485. _pISAPIContext != NULL )
  486. {
  487. DBG_ASSERT( _pISAPIContext != NULL );
  488. //
  489. // We don't know what the raw write filter will do so we better
  490. // have a thead available to prevent blocking
  491. //
  492. AddWorkerThread();
  493. hr = _pISAPIContext->ProcessRawWriteData( &rawStreamInfo,
  494. &fComplete );
  495. RemoveWorkerThread();
  496. if ( FAILED( hr ) )
  497. {
  498. goto ExitPoint;
  499. }
  500. if ( fComplete )
  501. {
  502. StartClose();
  503. hr = S_OK;
  504. goto ExitPoint;
  505. }
  506. }
  507. //
  508. // Next notify SSL filter always
  509. //
  510. DBG_ASSERT( _pSSLContext != NULL );
  511. hr = _pSSLContext->ProcessRawWriteData( &rawStreamInfo,
  512. &fComplete );
  513. if ( FAILED( hr ) )
  514. {
  515. goto ExitPoint;
  516. }
  517. if ( fComplete )
  518. {
  519. StartClose();
  520. hr = S_OK;
  521. goto ExitPoint;
  522. }
  523. //
  524. // If there is data to send to the client, then do so now.
  525. // This check is done because the filter may decide to eat up all the
  526. // data to be sent
  527. //
  528. if ( _ulFilterBufferType == HttpFilterBufferHttpStream &&
  529. rawStreamInfo.pbBuffer != NULL &&
  530. rawStreamInfo.cbData != 0 )
  531. {
  532. //
  533. // If we got to here, then we have processed data to send to the client
  534. //
  535. //
  536. // The processed data that is passed along will be written
  537. // before our read buffer is posted.
  538. //
  539. hr = DoRawWrite( UL_CONTEXT_FLAG_ASYNC,
  540. rawStreamInfo.pbBuffer,
  541. rawStreamInfo.cbData,
  542. NULL );
  543. if ( FAILED( hr ) )
  544. {
  545. goto ExitPoint;
  546. }
  547. //
  548. // Try to post another AppRead if there is one queued
  549. // (by other words if multiple overlapped RawWrites limit was not reached)
  550. //
  551. fPostAppRead = FALSE;
  552. _AppReadQueueLock.WriteLock();
  553. if( _lQueuedAppReads != 0 )
  554. {
  555. fPostAppRead = TRUE;
  556. //
  557. // Only one thread a time is allowed to post new AppRead
  558. //
  559. _lQueuedAppReads--;
  560. }
  561. else
  562. {
  563. //
  564. // We are not allowed to post new AppRead now because there are
  565. // probably 2 outstanding RawWrites at this moment
  566. //
  567. _fAppReadInProgress = FALSE;
  568. }
  569. _AppReadQueueLock.WriteUnlock();
  570. }
  571. else
  572. {
  573. //
  574. // No data was written
  575. // we can safely make another AppRead
  576. // because we still hold _fAppReadInProgress set to TRUE
  577. //
  578. fPostAppRead = TRUE;
  579. }
  580. if ( fPostAppRead )
  581. {
  582. //
  583. // Kick off another app read
  584. //
  585. _ulAppReadFilterBuffer.pBuffer = _AppReadOverlapped.QueryDataBuffer();
  586. _ulAppReadFilterBuffer.BufferSize = _AppReadOverlapped.QueryDataBufferSize();
  587. hr = DoAppRead( UL_CONTEXT_FLAG_ASYNC,
  588. &_ulAppReadFilterBuffer,
  589. NULL );
  590. goto ExitPoint;
  591. }
  592. else
  593. {
  594. //
  595. // Raw Write completion will post app read
  596. //
  597. hr = S_OK;
  598. goto ExitPoint;
  599. }
  600. ExitPoint:
  601. //
  602. // Close connection if error was detected
  603. //
  604. if ( FAILED( hr ) )
  605. {
  606. StartClose();
  607. }
  608. //
  609. // Async App Read grabbed the reference. It is time to dereference now
  610. //
  611. DereferenceFiltChannelContext();
  612. return hr;
  613. }
  614. HRESULT
  615. FILTER_CHANNEL_CONTEXT::TryAppRead(
  616. VOID
  617. )
  618. /*++
  619. Routine Description:
  620. Only up to one outstanding AppRead is allowed in any moment
  621. because otherwise the order of data blocks sent out is not guaranteed
  622. This method takes care of handling queued AppReads(). If there
  623. is no AppRead in progress, it will try to get exclusive right
  624. to process AppRead and if it succeeds then new AppRead is posted
  625. Otherwise it will simply return with NO_ERROR;
  626. Arguments:
  627. Return Value:
  628. HRESULT
  629. --*/
  630. {
  631. BOOL fPostAppRead = FALSE;
  632. _AppReadQueueLock.WriteLock();
  633. if( !_fAppReadInProgress )
  634. {
  635. _fAppReadInProgress = TRUE;
  636. //
  637. // This thread was chosen to post app read
  638. //
  639. fPostAppRead = TRUE;
  640. }
  641. else
  642. {
  643. //
  644. // Queue AppRead.
  645. // Currently there is AppRead in progress and new one can start
  646. // only after it completed and made RawWrite call
  647. //
  648. _lQueuedAppReads++;
  649. }
  650. _AppReadQueueLock.WriteUnlock();
  651. if ( fPostAppRead )
  652. {
  653. //
  654. // Kick off another app read
  655. //
  656. _ulAppReadFilterBuffer.pBuffer = _AppReadOverlapped.QueryDataBuffer();
  657. _ulAppReadFilterBuffer.BufferSize = _AppReadOverlapped.QueryDataBufferSize();
  658. return DoAppRead( UL_CONTEXT_FLAG_ASYNC,
  659. &_ulAppReadFilterBuffer,
  660. NULL );
  661. }
  662. return NO_ERROR;
  663. }
  664. HRESULT
  665. FILTER_CHANNEL_CONTEXT::OnNewConnection(
  666. VOID
  667. )
  668. /*++
  669. Routine Description:
  670. Handle initial completion for the HttpFilterAccept()
  671. It is called from OnRawReadCompletion because New connection
  672. completion is special case of RawWriteCompletion
  673. Arguments:
  674. cbCompletion - Bytes of completion
  675. dwCompletionStatus - Completion error
  676. Return Value:
  677. HRESULT
  678. --*/
  679. {
  680. HRESULT hr = E_FAIL;
  681. _fNewConnection = FALSE;
  682. //
  683. // This is a new connection. We have one less FILTER_CHANNEL_CONTEXT to
  684. // listen for incoming requests. Correct that if necessary.
  685. //
  686. _pManager->DecrementAndManageOutstandingContexts();
  687. //
  688. // Convert the UL addresses into something nicer!
  689. //
  690. HTTP_TRANSPORT_ADDRESS *pAddress = &_pConnectionInfo->Address;
  691. _connectionContext.LocalAddressType = pAddress->pLocalAddress->sa_family;
  692. _connectionContext.RemoteAddressType = pAddress->pRemoteAddress->sa_family;
  693. if( pAddress->pLocalAddress->sa_family == AF_INET )
  694. {
  695. _connectionContext.SockLocalAddress.ipv4SockAddress
  696. = * (PSOCKADDR_IN)pAddress->pLocalAddress;
  697. }
  698. else if( pAddress->pLocalAddress->sa_family == AF_INET6 )
  699. {
  700. _connectionContext.SockLocalAddress.ipv6SockAddress
  701. = * (PSOCKADDR_IN6)pAddress->pLocalAddress;
  702. }
  703. else
  704. {
  705. DBG_ASSERT( FALSE );
  706. }
  707. if( pAddress->pRemoteAddress->sa_family == AF_INET )
  708. {
  709. _connectionContext.SockRemoteAddress.ipv4SockAddress
  710. = * (PSOCKADDR_IN)pAddress->pRemoteAddress;
  711. }
  712. else if( pAddress->pRemoteAddress->sa_family == AF_INET6 )
  713. {
  714. _connectionContext.SockRemoteAddress.ipv6SockAddress
  715. = * (PSOCKADDR_IN6)pAddress->pRemoteAddress;
  716. }
  717. else
  718. {
  719. DBG_ASSERT( FALSE );
  720. }
  721. _connectionContext.fIsSecure = FALSE;
  722. _connectionContext.RawConnectionId = _pConnectionInfo->ConnectionId;
  723. //
  724. // create ISAPI_STREAM_CONTEXT
  725. // if ISAPI filters are enabled
  726. //
  727. // Endpoint config may contain information about explicitly
  728. // disabling raw ISAPI filter handling
  729. //
  730. if ( _pManager->QueryNotifyISAPIFilters() )
  731. {
  732. //
  733. // Lookup the endpoint config
  734. //
  735. hr = ENDPOINT_CONFIG::GetEndpointConfig( &_connectionContext,
  736. &_pEndpointConfig,
  737. TRUE /*fCreateEmptyIfNotFound*/);
  738. if ( FAILED( hr ) )
  739. {
  740. return hr;
  741. }
  742. DBG_ASSERT( _pEndpointConfig != NULL );
  743. //
  744. // HttpApi Config store may contain endpoint flag
  745. // that will prevent raw ISAPI Filter execution
  746. // on the endpoint data
  747. // Create ISAPI context only if Raw Filter handling is enabled
  748. //
  749. if ( !_pEndpointConfig->QueryNoRawFilter() )
  750. {
  751. hr =ISAPI_STREAM_CONTEXT::CreateContext(
  752. this,
  753. &_pISAPIContext );
  754. if ( hr == HRESULT_FROM_WIN32( ERROR_SERVICE_NOT_ACTIVE ) )
  755. {
  756. //
  757. // this error means that w3svc is shutting down so
  758. // there is no more need to create ISAPI_STREAM_CONTEXT
  759. //
  760. _pISAPIContext = NULL;
  761. }
  762. else if ( FAILED( hr ) )
  763. {
  764. return hr;
  765. }
  766. }
  767. }
  768. if ( _pISAPIContext != NULL )
  769. {
  770. _connectionContext.pfnSendDataBack = ISAPI_STREAM_CONTEXT::SendDataBack;
  771. }
  772. _connectionContext.pvStreamContext = this;
  773. //
  774. // copy out the server name.
  775. //
  776. _connectionContext.ClientSSLContextLength =
  777. _pConnectionInfo->ClientSSLContextLength;
  778. _connectionContext.pClientSSLContext =
  779. _pConnectionInfo->pClientSSLContext;
  780. //
  781. // Fill in our read buffer (as if we had read it in directly)
  782. //
  783. _cbRawReadData = _pConnectionInfo->InitialDataSize;
  784. if ( !_RawReadOverlapped.ResizeDataBuffer(
  785. max( _pConnectionInfo->InitialDataSize,
  786. QueryNextRawReadSize() ) ) )
  787. {
  788. return HRESULT_FROM_WIN32( GetLastError() );
  789. }
  790. memcpy( _RawReadOverlapped.QueryDataBuffer(),
  791. _pConnectionInfo->pInitialData,
  792. _pConnectionInfo->InitialDataSize );
  793. //
  794. // First indicate a new connection
  795. //
  796. DBG_ASSERT( _pSSLContext != NULL );
  797. //
  798. // We pass _pEndpointConfig but it may be empty.
  799. // In that case SSL Context will have to make a lookup
  800. //
  801. hr = _pSSLContext->ProcessNewConnection( &_connectionContext,
  802. _pEndpointConfig );
  803. if ( FAILED( hr ) )
  804. {
  805. return hr;
  806. }
  807. //
  808. // if _pISAPIContext == NULL then ISAPI notification
  809. // was not requested
  810. //
  811. if ( _pISAPIContext != NULL )
  812. {
  813. //
  814. // We don't know what the raw write filter will do so we better
  815. // have a thead available to prevent blocking
  816. //
  817. hr = _pISAPIContext->ProcessNewConnection(
  818. &_connectionContext,
  819. _pEndpointConfig
  820. );
  821. if ( FAILED( hr ) )
  822. {
  823. return hr;
  824. }
  825. }
  826. //
  827. // Adjust AppRead buffer size
  828. //
  829. if ( !_AppReadOverlapped.ResizeDataBuffer(
  830. FILTER_CHANNEL::QueryDefaultAppReadSize() ) )
  831. {
  832. return HRESULT_FROM_WIN32( GetLastError() );
  833. }
  834. //
  835. // Post one AppRead and queue another one
  836. // This will enable 2 outstanding RawWrites to exist
  837. // AppReads will be executed synchronously, so that
  838. // we don't lose order of incoming data but we will
  839. // not wait for completion of each RawWrite before
  840. // starting New AppRead
  841. //
  842. _lQueuedAppReads = 1;
  843. _fAppReadInProgress = TRUE;
  844. _ulAppReadFilterBuffer.pBuffer = _AppReadOverlapped.QueryDataBuffer();
  845. _ulAppReadFilterBuffer.BufferSize = _AppReadOverlapped.QueryDataBufferSize();
  846. return DoAppRead( UL_CONTEXT_FLAG_ASYNC,
  847. &_ulAppReadFilterBuffer,
  848. NULL );
  849. }
  850. HRESULT
  851. FILTER_CHANNEL_CONTEXT::OnRawReadCompletion(
  852. DWORD cbCompletion,
  853. DWORD dwCompletionStatus
  854. )
  855. /*++
  856. Routine Description:
  857. Get read completions off the wire. This includes the initial
  858. completion for the HttpFilterAccept()
  859. Arguments:
  860. cbCompletion - Bytes of completion
  861. dwCompletionStatus - Completion error
  862. Return Value:
  863. HRESULT
  864. --*/
  865. {
  866. HRESULT hr;
  867. BOOL fReadMore = FALSE;
  868. BOOL fComplete = FALSE;
  869. RAW_STREAM_INFO rawStreamInfo;
  870. //
  871. // Handle errors
  872. //
  873. if ( dwCompletionStatus != NO_ERROR )
  874. {
  875. if ( _fNewConnection )
  876. {
  877. _pManager->DecrementAndManageOutstandingContexts();
  878. }
  879. hr = HRESULT_FROM_WIN32( dwCompletionStatus );
  880. goto ExitPoint;
  881. }
  882. if ( cbCompletion == 0 )
  883. {
  884. //
  885. // Handle graceful disconnect
  886. //
  887. _ulAppWriteFilterBuffer.BufferType = HttpFilterBufferNotifyDisconnect;
  888. _ulAppWriteFilterBuffer.pBuffer = NULL;
  889. _ulAppWriteFilterBuffer.BufferSize = 0;
  890. //
  891. // no more RawRead will be launched
  892. //
  893. hr = DoAppWrite(UL_CONTEXT_FLAG_ASYNC, &_ulAppWriteFilterBuffer, NULL);
  894. goto ExitPoint;
  895. }
  896. //
  897. // If this is a new connection, then grok connection information, and
  898. // maintain pending count
  899. //
  900. if ( _fNewConnection )
  901. {
  902. hr = OnNewConnection( );
  903. if ( FAILED( hr ) )
  904. {
  905. goto ExitPoint;
  906. }
  907. }
  908. else
  909. {
  910. _cbRawReadData += cbCompletion;
  911. }
  912. //
  913. // reset default raw read size
  914. //
  915. SetNextRawReadSize( DEFAULT_RAW_READ_SIZE );
  916. rawStreamInfo.pbBuffer = _RawReadOverlapped.QueryDataBuffer();
  917. rawStreamInfo.cbBuffer = _RawReadOverlapped.QueryDataBufferSize();
  918. rawStreamInfo.cbData = _cbRawReadData;
  919. //
  920. // First, we will notify SSL
  921. //
  922. DBG_ASSERT( _pSSLContext != NULL );
  923. hr = _pSSLContext->ProcessRawReadData( &rawStreamInfo,
  924. &fReadMore,
  925. &fComplete );
  926. if ( FAILED( hr ) )
  927. {
  928. goto ExitPoint;
  929. }
  930. _cbRawReadData = rawStreamInfo.cbData;
  931. //
  932. // If we need to read more data, then do so now
  933. //
  934. if ( fReadMore )
  935. {
  936. //
  937. // rawStreamInfo.pbBuffer may have been replaced by different buffer
  938. // in ProcessRawReadData() call.
  939. // copy data back to pbuffRawReadData
  940. //
  941. if ( rawStreamInfo.pbBuffer != _RawReadOverlapped.QueryDataBuffer() )
  942. {
  943. if ( !_RawReadOverlapped.ResizeDataBuffer( rawStreamInfo.cbData +
  944. QueryNextRawReadSize() ) )
  945. {
  946. hr = HRESULT_FROM_WIN32( GetLastError() );
  947. goto ExitPoint;
  948. }
  949. memmove( _RawReadOverlapped.QueryDataBuffer(),
  950. rawStreamInfo.pbBuffer,
  951. rawStreamInfo.cbData
  952. );
  953. }
  954. else
  955. {
  956. // no need to copy data but we still have to resize
  957. //
  958. if ( !_RawReadOverlapped.ResizeDataBuffer( rawStreamInfo.cbData +
  959. QueryNextRawReadSize() ) )
  960. {
  961. hr = HRESULT_FROM_WIN32( GetLastError() );
  962. goto ExitPoint;
  963. }
  964. }
  965. hr = DoRawRead( UL_CONTEXT_FLAG_ASYNC,
  966. _RawReadOverlapped.QueryDataBuffer() + _cbRawReadData,
  967. QueryNextRawReadSize(),
  968. NULL );
  969. goto ExitPoint;
  970. }
  971. if ( fComplete )
  972. {
  973. StartClose();
  974. hr = S_OK;
  975. goto ExitPoint;
  976. }
  977. //
  978. // Reset the next read size before calling into filters since SSL may
  979. // have done a really small read, just previous to this.
  980. //
  981. SetNextRawReadSize( FILTER_CHANNEL::QueryDefaultRawReadSize() );
  982. //
  983. // Now we can start notifying ISAPI filters if needed (and there is
  984. // data to process)
  985. //
  986. if ( _pISAPIContext != NULL )
  987. {
  988. fComplete = FALSE;
  989. fReadMore = FALSE;
  990. AddWorkerThread();
  991. hr = _pISAPIContext->ProcessRawReadData( &rawStreamInfo,
  992. &fReadMore,
  993. &fComplete );
  994. RemoveWorkerThread();
  995. if ( FAILED( hr ) )
  996. {
  997. goto ExitPoint;
  998. }
  999. _cbRawReadData = rawStreamInfo.cbData;
  1000. //
  1001. // If we need to read more data, then do so now
  1002. //
  1003. if ( fReadMore )
  1004. {
  1005. //
  1006. // rawStreamInfo may have been replaced by different buffer
  1007. // in ProcessRawReadData() call.
  1008. // copy data back to pbufRawReadData
  1009. //
  1010. if ( rawStreamInfo.pbBuffer != _RawReadOverlapped.QueryDataBuffer() )
  1011. {
  1012. if ( !_RawReadOverlapped.ResizeDataBuffer( rawStreamInfo.cbData +
  1013. QueryNextRawReadSize() ) )
  1014. {
  1015. hr = HRESULT_FROM_WIN32( GetLastError() );
  1016. goto ExitPoint;
  1017. }
  1018. memmove( _RawReadOverlapped.QueryDataBuffer(),
  1019. rawStreamInfo.pbBuffer,
  1020. rawStreamInfo.cbData
  1021. );
  1022. }
  1023. else
  1024. {
  1025. // no need to copy data but we still have to resize
  1026. //
  1027. if ( !_RawReadOverlapped.ResizeDataBuffer( rawStreamInfo.cbData +
  1028. QueryNextRawReadSize() ) )
  1029. {
  1030. hr = HRESULT_FROM_WIN32( GetLastError() );
  1031. goto ExitPoint;
  1032. }
  1033. }
  1034. hr = DoRawRead( UL_CONTEXT_FLAG_ASYNC,
  1035. _RawReadOverlapped.QueryDataBuffer() + _cbRawReadData,
  1036. QueryNextRawReadSize(),
  1037. NULL );
  1038. goto ExitPoint;
  1039. }
  1040. if ( fComplete )
  1041. {
  1042. StartClose();
  1043. hr = S_OK;
  1044. goto ExitPoint;
  1045. }
  1046. }
  1047. //
  1048. // If after filtering there is data remaining in our buffer, then that
  1049. // data is destined to the application. Send it asynchronously because
  1050. // there is a risk that synchronous call gets blocked for a long time
  1051. //
  1052. _cbRawReadData = 0;
  1053. if ( rawStreamInfo.cbData != 0 )
  1054. {
  1055. //
  1056. // Reset default raw read size
  1057. //
  1058. SetNextRawReadSize( FILTER_CHANNEL::QueryDefaultRawReadSize() );
  1059. if ( !_RawReadOverlapped.ResizeDataBuffer( QueryNextRawReadSize() ) )
  1060. {
  1061. hr = HRESULT_FROM_WIN32( GetLastError() );
  1062. goto ExitPoint;
  1063. }
  1064. //
  1065. // Initiate a raw read that will send the data before posting the read.
  1066. //
  1067. _ulAppWriteAndRawReadFilterBuffer.BufferType = HttpFilterBufferHttpStream;
  1068. _ulAppWriteAndRawReadFilterBuffer.pBuffer = _RawReadOverlapped.QueryDataBuffer();
  1069. _ulAppWriteAndRawReadFilterBuffer.BufferSize = QueryNextRawReadSize();
  1070. _ulAppWriteAndRawReadFilterBuffer.pWriteBuffer = rawStreamInfo.pbBuffer;
  1071. _ulAppWriteAndRawReadFilterBuffer.WriteBufferSize = rawStreamInfo.cbData;
  1072. _ulAppWriteAndRawReadFilterBuffer.Reserved = _pConnectionInfo->ConnectionId;
  1073. hr = DoAppWriteAndRawRead(UL_CONTEXT_FLAG_ASYNC, &_ulAppWriteAndRawReadFilterBuffer);
  1074. if ( FAILED( hr ) )
  1075. {
  1076. goto ExitPoint;
  1077. }
  1078. }
  1079. else
  1080. {
  1081. //
  1082. // Kick off another raw read
  1083. //
  1084. //
  1085. // reset default raw read size
  1086. //
  1087. SetNextRawReadSize( FILTER_CHANNEL::QueryDefaultRawReadSize() );
  1088. if ( !_RawReadOverlapped.ResizeDataBuffer( QueryNextRawReadSize() ) )
  1089. {
  1090. hr = HRESULT_FROM_WIN32( GetLastError() );
  1091. goto ExitPoint;
  1092. }
  1093. hr = DoRawRead( UL_CONTEXT_FLAG_ASYNC,
  1094. _RawReadOverlapped.QueryDataBuffer(),
  1095. QueryNextRawReadSize() ,
  1096. NULL );
  1097. if ( FAILED( hr ) )
  1098. {
  1099. goto ExitPoint;
  1100. }
  1101. }
  1102. hr = S_OK;
  1103. ExitPoint:
  1104. //
  1105. // Close connection if error was detected
  1106. //
  1107. if ( FAILED( hr ) )
  1108. {
  1109. StartClose();
  1110. }
  1111. //
  1112. // Async Raw Read grabbed the reference.
  1113. // It is time to dereference now
  1114. //
  1115. DereferenceFiltChannelContext();
  1116. return hr;
  1117. }
  1118. HRESULT
  1119. FILTER_CHANNEL_CONTEXT::OnRawWriteCompletion(
  1120. DWORD /*cbCompletion*/,
  1121. DWORD dwCompletionStatus,
  1122. UL_OVERLAPPED_CONTEXT * pContextOverlapped
  1123. )
  1124. /*++
  1125. Routine Description:
  1126. after raw write completes, this routine has to assure that new asynchronous AppRead request is
  1127. made to continue properly in communication
  1128. Note: This completion should be caused only by asynchronous DoRawWrite started in completion routine
  1129. of AppRead (OnAppReadCompletion()).
  1130. Please assure that NO RawWrite that is initiated by data coming from RawRead (SSL handshake)
  1131. will be called asynchronously. That could cause race condition (multiple threads using the same buffer
  1132. eg. for SSL data encryption)
  1133. Arguments:
  1134. cbCompletion - Bytes of completion (currently not used)
  1135. dwCompletionStatus - Completion error
  1136. Return Value:
  1137. HRESULT
  1138. --*/
  1139. {
  1140. HRESULT hr = E_FAIL;
  1141. switch ( pContextOverlapped->QuerySubtype() )
  1142. {
  1143. case UL_OVERLAPPED_CONTEXT_COMPLETION_CALLBACK:
  1144. {
  1145. //
  1146. // delete context buffer allocated by SSPI package
  1147. //
  1148. hr = pContextOverlapped->DoCallback();
  1149. //
  1150. // time to delete temporary overlapped context
  1151. //
  1152. delete pContextOverlapped;
  1153. pContextOverlapped = NULL;
  1154. // if completion status failed then return completion
  1155. // status, otherwise hr of the DoCallback
  1156. if ( dwCompletionStatus != NO_ERROR )
  1157. {
  1158. break;
  1159. }
  1160. else
  1161. {
  1162. goto ExitPoint;
  1163. }
  1164. }
  1165. case UL_OVERLAPPED_CONTEXT_TEMPORARY:
  1166. //
  1167. // time to delete temporary overlapped context
  1168. //
  1169. delete pContextOverlapped;
  1170. pContextOverlapped = NULL;
  1171. break;
  1172. case UL_OVERLAPPED_CONTEXT_DATA:
  1173. //
  1174. // make overlapped to be available for next useq
  1175. //
  1176. ReleaseRawWriteBuffer( pContextOverlapped );
  1177. if ( dwCompletionStatus != NO_ERROR )
  1178. {
  1179. break;
  1180. }
  1181. //
  1182. // raw write completion triggers new AppRead
  1183. // but there is only one outstanding AppRead allowed
  1184. // a time ( while we have 2 outstanding RawWrites
  1185. // to emilinate the delayed ACK problem - see Windows Bugs 394511 )
  1186. //
  1187. hr = TryAppRead();
  1188. goto ExitPoint;
  1189. default:
  1190. DBG_ASSERT(FALSE);
  1191. hr = E_FAIL;
  1192. goto ExitPoint;
  1193. }
  1194. //
  1195. // completion status must be returned
  1196. //
  1197. hr = HRESULT_FROM_WIN32( dwCompletionStatus );
  1198. ExitPoint:
  1199. //
  1200. // Close connection if error was detected
  1201. //
  1202. if ( FAILED( hr ) )
  1203. {
  1204. StartClose();
  1205. }
  1206. //
  1207. // Async Raw Write grabbed the reference.
  1208. // It is time to dereference now
  1209. //
  1210. DereferenceFiltChannelContext();
  1211. return hr;
  1212. }
  1213. HRESULT
  1214. FILTER_CHANNEL_CONTEXT::OnAppWriteCompletion(
  1215. DWORD /*cbCompletion*/,
  1216. DWORD dwCompletionStatus
  1217. )
  1218. /*++
  1219. Routine Description:
  1220. OnAppWrite completion should be called only after handling
  1221. graceful disconnect. All the other AppWrites must happen with
  1222. DoAppWriteAndRawRead()
  1223. Arguments:
  1224. cbCompletion - Bytes of completion (currently not used)
  1225. dwCompletionStatus - Completion error
  1226. Return Value:
  1227. HRESULT
  1228. --*/
  1229. {
  1230. HRESULT hr = HRESULT_FROM_WIN32( dwCompletionStatus );
  1231. //
  1232. // Close connection if error was detected
  1233. //
  1234. if ( FAILED( hr ) )
  1235. {
  1236. StartClose();
  1237. }
  1238. //
  1239. // Async App Write grabbed the reference.
  1240. // It is time to dereference now
  1241. //
  1242. DereferenceFiltChannelContext();
  1243. return hr;
  1244. }
  1245. HRESULT
  1246. FILTER_CHANNEL_CONTEXT::DoAppWriteAndRawRead(
  1247. DWORD dwFlags,
  1248. PHTTP_FILTER_BUFFER_PLUS pHttpBufferPlus
  1249. )
  1250. /*++
  1251. Routine Description:
  1252. Write data to the app and read some bytes from the wire
  1253. Arguments:
  1254. dwFlags - UL_CONTEXT_ASYNC for async
  1255. pHttpBufferPlus - read and write buffers
  1256. Return Value:
  1257. HRESULT
  1258. --*/
  1259. {
  1260. BOOL fAsync = !!( dwFlags & UL_CONTEXT_FLAG_ASYNC );
  1261. ULONG ulRet = ERROR_SUCCESS;
  1262. HRESULT hr = NO_ERROR;
  1263. IF_DEBUG( APP_RAW_READWRITE )
  1264. {
  1265. DBGPRINTF(( DBG_CONTEXT,
  1266. "ENTER DoAppWriteAndRawRead( async:%d )\n",
  1267. fAsync
  1268. ));
  1269. }
  1270. if ( fAsync )
  1271. {
  1272. ReferenceFiltChannelContext();
  1273. }
  1274. ulRet = HttpFilterAppWriteAndRawRead( _pManager->QueryFilterHandle(),
  1275. pHttpBufferPlus,
  1276. fAsync ? QueryRawReadOverlapped() : NULL);
  1277. if ( fAsync )
  1278. {
  1279. if ( ulRet == NO_ERROR )
  1280. {
  1281. ulRet = ERROR_IO_PENDING;
  1282. }
  1283. if ( ulRet != ERROR_IO_PENDING )
  1284. {
  1285. DereferenceFiltChannelContext();
  1286. hr = HRESULT_FROM_WIN32( ulRet );
  1287. }
  1288. }
  1289. else
  1290. {
  1291. if ( ulRet != NO_ERROR )
  1292. {
  1293. hr = HRESULT_FROM_WIN32( ulRet );
  1294. }
  1295. }
  1296. IF_DEBUG( APP_RAW_READWRITE )
  1297. {
  1298. DBGPRINTF(( DBG_CONTEXT,
  1299. "LEAVE DoAppWriteAndRawRead( async:%d )\n",
  1300. fAsync
  1301. ));
  1302. }
  1303. return hr;
  1304. }
  1305. HRESULT
  1306. FILTER_CHANNEL_CONTEXT::DoRawWrite(
  1307. DWORD dwFlags,
  1308. PVOID pvBuffer,
  1309. DWORD cbBuffer,
  1310. DWORD * pcbWritten,
  1311. UL_OVERLAPPED_CONTEXT::PFN_CALLBACK pfnCallback,
  1312. PVOID pCallbackParam
  1313. )
  1314. /*++
  1315. Routine Description:
  1316. Write some bytes to the wire
  1317. Arguments:
  1318. dwFlags - UL_CONTEXT_ASYNC for async
  1319. pvBuffer - Buffer to send
  1320. cbBuffer - bytes in buffer
  1321. pcbWritten - Bytes written
  1322. pfnCallback - optional Callback function - default is NULL
  1323. pCallbackParam - callback parameter -default is NULL
  1324. Return Value:
  1325. HRESULT
  1326. --*/
  1327. {
  1328. BOOL fAsync = !!( dwFlags & UL_CONTEXT_FLAG_ASYNC );
  1329. ULONG ulRet = ERROR_SUCCESS;
  1330. HRESULT hr = NO_ERROR;
  1331. OVERLAPPED * pOverlapped = NULL;
  1332. UL_OVERLAPPED_CONTEXT * pContextOverlappedBuffered = NULL;
  1333. IF_DEBUG( APP_RAW_READWRITE )
  1334. {
  1335. DBGPRINTF(( DBG_CONTEXT,
  1336. "ENTER DoRawWrite( async:%d, buffered:%d, bytes:%d )\n",
  1337. fAsync,
  1338. !!( dwFlags & UL_CONTEXT_FLAG_BUFFERED ),
  1339. cbBuffer
  1340. ));
  1341. }
  1342. if ( fAsync )
  1343. {
  1344. if ( dwFlags & UL_CONTEXT_FLAG_COMPLETION_CALLBACK )
  1345. {
  1346. //
  1347. // Create new temporary overlapped context
  1348. //
  1349. pContextOverlappedBuffered
  1350. = new UL_OVERLAPPED_CONTEXT( UL_OVERLAPPED_CONTEXT_RAW_WRITE,
  1351. UL_OVERLAPPED_CONTEXT_COMPLETION_CALLBACK );
  1352. if ( pContextOverlappedBuffered == NULL )
  1353. {
  1354. hr = HRESULT_FROM_WIN32( ERROR_OUTOFMEMORY );
  1355. goto Finished;
  1356. }
  1357. //
  1358. // Configure new overlapped context
  1359. //
  1360. pContextOverlappedBuffered->SetContext( this );
  1361. pContextOverlappedBuffered->SetCallBack( pfnCallback,
  1362. pCallbackParam );
  1363. //
  1364. // retrieve overlapped to be used for this RawWrite
  1365. //
  1366. pOverlapped = pContextOverlappedBuffered->QueryOverlapped();
  1367. }
  1368. else if ( dwFlags & UL_CONTEXT_FLAG_BUFFERED )
  1369. {
  1370. //
  1371. // BUFFERED flag is set - we will make private copy
  1372. // of the data to be sent to enable caller to use
  1373. // it's buffer upon completion
  1374. //
  1375. //
  1376. // Create new temporary overlapped context
  1377. //
  1378. pContextOverlappedBuffered
  1379. = new UL_OVERLAPPED_CONTEXT( UL_OVERLAPPED_CONTEXT_RAW_WRITE,
  1380. UL_OVERLAPPED_CONTEXT_TEMPORARY );
  1381. if ( pContextOverlappedBuffered == NULL )
  1382. {
  1383. hr = HRESULT_FROM_WIN32( ERROR_OUTOFMEMORY );
  1384. goto Finished;
  1385. }
  1386. //
  1387. // Configure new overlapped context
  1388. //
  1389. pContextOverlappedBuffered->SetContext( this );
  1390. //
  1391. // copy data to be sent to private buffer
  1392. // that is member of UL_OVERLAPPED_CONTEXT
  1393. //
  1394. if ( !pContextOverlappedBuffered->ResizeDataBuffer( cbBuffer ) )
  1395. {
  1396. hr = HRESULT_FROM_WIN32( ERROR_OUTOFMEMORY );
  1397. goto Finished;
  1398. }
  1399. memcpy( pContextOverlappedBuffered->QueryDataBuffer(),
  1400. (PBYTE) pvBuffer,
  1401. cbBuffer );
  1402. //
  1403. // instead of data buffer passed by caller our private
  1404. // buffer will be used. Thus caller will be able to reclaim
  1405. // it's buffer after returing from this call without
  1406. // waiting for completion
  1407. //
  1408. pvBuffer = pContextOverlappedBuffered->QueryDataBuffer();
  1409. //
  1410. // retrieve overlapped to be used for this RawWrite
  1411. //
  1412. pOverlapped = pContextOverlappedBuffered->QueryOverlapped();
  1413. }
  1414. else
  1415. {
  1416. //
  1417. // Not buffered send.
  1418. // We have to determine which Overlapped context to use
  1419. // If pvBuffer was acquired by AcquireRawWriteBuffer()
  1420. // then _pLastAcquiredRawWriteOverlapped is not NULL
  1421. // and is pointing to the structure that contains the acquired buffer
  1422. //
  1423. UL_OVERLAPPED_CONTEXT * pRawWriteUlOverlapped = QueryLastAcquiredRawWriteBufferOverlapped();
  1424. if ( pRawWriteUlOverlapped == NULL ||
  1425. pRawWriteUlOverlapped->QueryDataBuffer() != (PBYTE) pvBuffer )
  1426. {
  1427. //
  1428. // This data must be coming from rawdata filter
  1429. // when SSL is not used (SSL will always use
  1430. // buffers that are returned by AcquireRawWriteBuffer())
  1431. //
  1432. // It is necessary to copy data to private buffer
  1433. // in order to be able to maintain 2 outstanding
  1434. // RawWrites
  1435. //
  1436. PBYTE pbRawWriteBuffer = NULL;
  1437. hr = AcquireRawWriteBuffer( &pbRawWriteBuffer,
  1438. cbBuffer );
  1439. if ( FAILED( hr ) )
  1440. {
  1441. goto Finished;
  1442. }
  1443. memcpy( pbRawWriteBuffer,
  1444. (PBYTE) pvBuffer,
  1445. cbBuffer );
  1446. pvBuffer = (PVOID) pbRawWriteBuffer;
  1447. //
  1448. // now it's guaranteed that we use one of the
  1449. // DATA1 or DATA2 buffers for RawWrite
  1450. // let's find out the associated overlapped
  1451. //
  1452. pRawWriteUlOverlapped =
  1453. QueryLastAcquiredRawWriteBufferOverlapped();
  1454. DBG_ASSERT( pRawWriteUlOverlapped != NULL );
  1455. }
  1456. pOverlapped = pRawWriteUlOverlapped->QueryOverlapped();
  1457. }
  1458. //
  1459. // For all asynchonous we have to reference FiltChannelContext
  1460. //
  1461. ReferenceFiltChannelContext();
  1462. }
  1463. else
  1464. {
  1465. pOverlapped = NULL;
  1466. }
  1467. ulRet = HttpFilterRawWrite( _pManager->QueryFilterHandle(),
  1468. _pConnectionInfo->ConnectionId,
  1469. pvBuffer,
  1470. cbBuffer,
  1471. pcbWritten,
  1472. pOverlapped );
  1473. if ( fAsync )
  1474. {
  1475. if ( ulRet == NO_ERROR )
  1476. {
  1477. ulRet = ERROR_IO_PENDING;
  1478. }
  1479. if ( ulRet != ERROR_IO_PENDING )
  1480. {
  1481. DereferenceFiltChannelContext();
  1482. hr = HRESULT_FROM_WIN32( ulRet );
  1483. goto Finished;
  1484. }
  1485. else
  1486. {
  1487. hr = NO_ERROR;
  1488. }
  1489. }
  1490. else
  1491. {
  1492. //
  1493. // for synchronous sends the raw write buffers must
  1494. // be released if they are owned by the
  1495. // FILTER_CHANNEL_CONTEXT
  1496. //
  1497. TryReleaseLastAcquiredRawWriteBuffer();
  1498. if ( ulRet != NO_ERROR )
  1499. {
  1500. hr = HRESULT_FROM_WIN32( ulRet );
  1501. goto Finished;
  1502. }
  1503. }
  1504. Finished:
  1505. if ( FAILED( hr ) )
  1506. {
  1507. if ( pContextOverlappedBuffered != NULL )
  1508. {
  1509. delete pContextOverlappedBuffered;
  1510. pContextOverlappedBuffered = NULL;
  1511. }
  1512. }
  1513. IF_DEBUG( APP_RAW_READWRITE )
  1514. {
  1515. DBGPRINTF(( DBG_CONTEXT,
  1516. "LEAVE DoRawWrite( async:%d, bytes:%d ) hr=0x%x\n",
  1517. fAsync,
  1518. cbBuffer,
  1519. hr
  1520. ));
  1521. }
  1522. return hr;
  1523. }
  1524. HRESULT
  1525. FILTER_CHANNEL_CONTEXT::DoAppRead(
  1526. DWORD dwFlags,
  1527. HTTP_FILTER_BUFFER * pFilterBuffer,
  1528. DWORD * pcbRead
  1529. )
  1530. /*++
  1531. Routine Description:
  1532. Read data from application
  1533. Arguments:
  1534. dwFlags - UL_CONTEXT_ASYNC for async
  1535. pFilterBuffer - Filter buffer
  1536. pcbRead - Bytes read
  1537. Return Value:
  1538. HRESULT
  1539. --*/
  1540. {
  1541. BOOL fAsync = !!( dwFlags & UL_CONTEXT_FLAG_ASYNC );
  1542. ULONG ulRet = ERROR_SUCCESS;
  1543. HRESULT hr = NO_ERROR;
  1544. IF_DEBUG( APP_RAW_READWRITE )
  1545. {
  1546. DBGPRINTF(( DBG_CONTEXT,
  1547. "ENTER DoAppRead( async:%d )\n",
  1548. fAsync
  1549. ));
  1550. }
  1551. if ( fAsync )
  1552. {
  1553. ReferenceFiltChannelContext();
  1554. }
  1555. ulRet = HttpFilterAppRead( _pManager->QueryFilterHandle(),
  1556. _pConnectionInfo->ConnectionId,
  1557. pFilterBuffer,
  1558. pFilterBuffer->BufferSize,
  1559. pcbRead,
  1560. fAsync ? QueryAppReadOverlapped() : NULL);
  1561. if ( fAsync )
  1562. {
  1563. if ( ulRet == NO_ERROR )
  1564. {
  1565. ulRet = ERROR_IO_PENDING;
  1566. }
  1567. if ( ulRet != ERROR_IO_PENDING )
  1568. {
  1569. DereferenceFiltChannelContext();
  1570. hr = HRESULT_FROM_WIN32( ulRet );
  1571. }
  1572. }
  1573. else
  1574. {
  1575. if ( ulRet != NO_ERROR )
  1576. {
  1577. hr = HRESULT_FROM_WIN32( ulRet );
  1578. }
  1579. }
  1580. IF_DEBUG( APP_RAW_READWRITE )
  1581. {
  1582. DBGPRINTF(( DBG_CONTEXT,
  1583. "LEAVE DoAppRead( async:%d )\n",
  1584. fAsync
  1585. ));
  1586. }
  1587. return hr;
  1588. }
  1589. HRESULT
  1590. FILTER_CHANNEL_CONTEXT::DoAppWrite(
  1591. DWORD dwFlags,
  1592. HTTP_FILTER_BUFFER * pFilterBuffer,
  1593. DWORD * pcbWritten
  1594. )
  1595. /*++
  1596. Routine Description:
  1597. Write data to the application
  1598. Arguments:
  1599. dwFlags - UL_CONTEXT_ASYNC for async
  1600. pFilterBuffer - Filter buffer
  1601. pcbWritten - Bytes written
  1602. Return Value:
  1603. HRESULT
  1604. --*/
  1605. {
  1606. BOOL fAsync = !!( dwFlags & UL_CONTEXT_FLAG_ASYNC );
  1607. ULONG ulRet = ERROR_SUCCESS;
  1608. HRESULT hr = NO_ERROR;
  1609. DBG_ASSERT( pFilterBuffer != NULL );
  1610. IF_DEBUG( APP_RAW_READWRITE )
  1611. {
  1612. DBGPRINTF(( DBG_CONTEXT,
  1613. "ENTER DoAppWrite( async:%d, bytes:%d, buffertype:%d )\n",
  1614. fAsync,
  1615. pFilterBuffer->BufferSize,
  1616. pFilterBuffer->BufferType
  1617. ));
  1618. }
  1619. if ( fAsync )
  1620. {
  1621. ReferenceFiltChannelContext();
  1622. }
  1623. ulRet = HttpFilterAppWrite( _pManager->QueryFilterHandle(),
  1624. _pConnectionInfo->ConnectionId,
  1625. pFilterBuffer,
  1626. pFilterBuffer->BufferSize,
  1627. pcbWritten,
  1628. fAsync ? QueryAppWriteOverlapped() : NULL );
  1629. if ( fAsync )
  1630. {
  1631. if ( ulRet == NO_ERROR )
  1632. {
  1633. ulRet = ERROR_IO_PENDING;
  1634. }
  1635. if ( ulRet != ERROR_IO_PENDING )
  1636. {
  1637. DereferenceFiltChannelContext();
  1638. hr = HRESULT_FROM_WIN32( ulRet );
  1639. }
  1640. }
  1641. else
  1642. {
  1643. if ( ulRet != NO_ERROR )
  1644. {
  1645. hr = HRESULT_FROM_WIN32( ulRet );
  1646. }
  1647. }
  1648. IF_DEBUG( APP_RAW_READWRITE )
  1649. {
  1650. DBGPRINTF(( DBG_CONTEXT,
  1651. "LEAVE DoAppWrite( async:%d, bytes:%d, buffertype:%d ) hr=0x%x\n",
  1652. fAsync,
  1653. pFilterBuffer->BufferSize,
  1654. pFilterBuffer->BufferType,
  1655. hr
  1656. ));
  1657. }
  1658. return hr;
  1659. }
  1660. HRESULT
  1661. FILTER_CHANNEL_CONTEXT::DoRawRead(
  1662. DWORD dwFlags,
  1663. PVOID pvBuffer,
  1664. DWORD cbBuffer,
  1665. DWORD * pcbWritten
  1666. )
  1667. /*++
  1668. Routine Description:
  1669. Read some bytes from the wire
  1670. Arguments:
  1671. dwFlags - UL_CONTEXT_ASYNC for async
  1672. pvBuffer - buffer
  1673. cbBuffer - bytes in buffer
  1674. pcbWritten - Bytes written
  1675. Return Value:
  1676. HRESULT
  1677. --*/
  1678. {
  1679. BOOL fAsync = !!( dwFlags & UL_CONTEXT_FLAG_ASYNC );
  1680. ULONG ulRet = ERROR_SUCCESS;
  1681. HRESULT hr = NO_ERROR;
  1682. IF_DEBUG( APP_RAW_READWRITE )
  1683. {
  1684. DBGPRINTF(( DBG_CONTEXT,
  1685. "ENTER DoRawRead( async:%d )\n",
  1686. fAsync
  1687. ));
  1688. }
  1689. if ( fAsync )
  1690. {
  1691. ReferenceFiltChannelContext();
  1692. }
  1693. ulRet = HttpFilterRawRead( _pManager->QueryFilterHandle(),
  1694. _pConnectionInfo->ConnectionId,
  1695. pvBuffer,
  1696. cbBuffer,
  1697. pcbWritten,
  1698. fAsync ? QueryRawReadOverlapped() : NULL);
  1699. if ( fAsync )
  1700. {
  1701. if ( ulRet == NO_ERROR )
  1702. {
  1703. ulRet = ERROR_IO_PENDING;
  1704. }
  1705. if ( ulRet != ERROR_IO_PENDING )
  1706. {
  1707. DereferenceFiltChannelContext();
  1708. hr = HRESULT_FROM_WIN32( ulRet );
  1709. }
  1710. }
  1711. else
  1712. {
  1713. if ( ulRet != NO_ERROR )
  1714. {
  1715. hr = HRESULT_FROM_WIN32( ulRet );
  1716. }
  1717. }
  1718. IF_DEBUG( APP_RAW_READWRITE )
  1719. {
  1720. DBGPRINTF(( DBG_CONTEXT,
  1721. "LEAVE DoRawRead( async:%d )\n",
  1722. fAsync
  1723. ));
  1724. }
  1725. return hr;
  1726. }
  1727. VOID
  1728. FILTER_CHANNEL_CONTEXT::StartClose(
  1729. VOID
  1730. )
  1731. /*++
  1732. Routine Description:
  1733. Start the process of closing the connection (and cleaning up FILTER_CHANNEL_CONTEXT)
  1734. Arguments:
  1735. None
  1736. Return Value:
  1737. None
  1738. --*/
  1739. {
  1740. BOOL fOld;
  1741. fOld = (BOOL) InterlockedCompareExchange( (PLONG) &_fCloseConnection,
  1742. TRUE,
  1743. FALSE );
  1744. if ( fOld == FALSE )
  1745. {
  1746. // _fNewConnection = TRUE indicates that
  1747. // there should not be valid connection info so there is nothing to be closed
  1748. if( _pManager->QueryFilterHandle() != NULL && !_fNewConnection )
  1749. {
  1750. ULONG ulRet = ERROR_SUCCESS;
  1751. //
  1752. // We don't have to grab the reference because
  1753. // we use the initial connection reference
  1754. //
  1755. ulRet = HttpFilterClose( _pManager->QueryFilterHandle(),
  1756. _pConnectionInfo->ConnectionId,
  1757. QueryCloseOverlapped() );
  1758. if ( ulRet == NO_ERROR )
  1759. {
  1760. //
  1761. // Both NO_ERROR and ERROR_IO_PENDING
  1762. // are expected to go the completion path
  1763. //
  1764. ulRet = ERROR_IO_PENDING;
  1765. }
  1766. if ( ulRet != ERROR_IO_PENDING )
  1767. {
  1768. //
  1769. // Note: ERROR_INVALID_PARAMETER may be received if client
  1770. // already closed the connection (connection ID will be considered invalid
  1771. // from the http.sys point of view).
  1772. //
  1773. // Notify about closing and do the final dereference
  1774. //
  1775. CloseNotify();
  1776. DereferenceFiltChannelContext();
  1777. }
  1778. }
  1779. else
  1780. {
  1781. //
  1782. // We were the ones to set the flag. Do the final dereference
  1783. //
  1784. DereferenceFiltChannelContext();
  1785. }
  1786. }
  1787. else
  1788. {
  1789. //
  1790. // Someone else has set the flag. Let them dereference
  1791. //
  1792. }
  1793. }
  1794. HRESULT
  1795. FILTER_CHANNEL_CONTEXT::DoAccept(
  1796. VOID
  1797. )
  1798. /*++
  1799. Routine Description:
  1800. Accept an incoming connection by calling HttpFilterAccept()
  1801. Arguments:
  1802. None
  1803. Return Value:
  1804. HRESULT
  1805. --*/
  1806. {
  1807. ULONG ulRet;
  1808. HRESULT hr = NO_ERROR;
  1809. ReferenceFiltChannelContext();
  1810. ulRet = HttpFilterAccept( _pManager->QueryFilterHandle(),
  1811. _pConnectionInfo,
  1812. _buffConnectionInfo.QuerySize(),
  1813. NULL,
  1814. QueryRawReadOverlapped() );
  1815. if ( ulRet != ERROR_IO_PENDING )
  1816. {
  1817. hr = HRESULT_FROM_WIN32( ulRet );
  1818. DereferenceFiltChannelContext();
  1819. DBGPRINTF(( DBG_CONTEXT,
  1820. "Error calling HttpFilterAccept(). hr = %x\n",
  1821. hr ));
  1822. }
  1823. else
  1824. {
  1825. //
  1826. // Another outstanding context available!
  1827. //
  1828. _pManager->IncrementOutstandingContexts();
  1829. }
  1830. return hr;
  1831. }
  1832. HRESULT
  1833. FILTER_CHANNEL_CONTEXT::SendDataBack(
  1834. RAW_STREAM_INFO * pRawStreamInfo
  1835. )
  1836. /*++
  1837. Routine Description:
  1838. Sends given data back to client, while going with the ssl filter
  1839. if necessary
  1840. Arguments:
  1841. pRawStreamInfo - Raw data to send back
  1842. Return Value:
  1843. HRESULT
  1844. --*/
  1845. {
  1846. if ( pRawStreamInfo == NULL )
  1847. {
  1848. DBG_ASSERT( FALSE );
  1849. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  1850. }
  1851. DBG_ASSERT( _pSSLContext != NULL );
  1852. //
  1853. // ISAPI filter has sent back some data in a raw notification.
  1854. // Have SSL process it and then send it here
  1855. //
  1856. HRESULT hr = _pSSLContext->SendDataBack( pRawStreamInfo );
  1857. if ( FAILED( hr ) )
  1858. {
  1859. return hr;
  1860. }
  1861. //
  1862. // Send back the data
  1863. //
  1864. // bump up the number of threads because
  1865. // this is synchronous call that may block our thread
  1866. // for quite a while
  1867. //
  1868. AddWorkerThread();
  1869. hr = DoRawWrite( UL_CONTEXT_FLAG_SYNC,
  1870. pRawStreamInfo->pbBuffer,
  1871. pRawStreamInfo->cbData,
  1872. NULL );
  1873. RemoveWorkerThread();
  1874. return hr;
  1875. }
  1876. VOID
  1877. FILTER_CHANNEL_CONTEXT::CloseNotify(
  1878. VOID
  1879. )
  1880. /*++
  1881. Routine Description:
  1882. Notify ISAPI Filter (if present) or whoever else interested
  1883. that connection was closed
  1884. Arguments:
  1885. None
  1886. Return Value:
  1887. VOID
  1888. --*/
  1889. {
  1890. //
  1891. // Notify ISAPIs of the close
  1892. //
  1893. if ( _pISAPIContext != NULL )
  1894. {
  1895. //
  1896. // We don't know what the raw write filter will do so we better
  1897. // have a thead available to prevent blocking
  1898. //
  1899. AddWorkerThread();
  1900. _pISAPIContext->ProcessConnectionClose();
  1901. RemoveWorkerThread();
  1902. }
  1903. }
  1904. //
  1905. // Constructor
  1906. //
  1907. FILTER_CHANNEL::FILTER_CHANNEL(
  1908. LPWSTR pwszFilterChannelName
  1909. )
  1910. {
  1911. _dwInitcsFiltChannelContexts = 0;
  1912. _cFiltChannelContexts = 0;
  1913. _hFilterHandle = NULL;
  1914. _lStartedListening = 0;
  1915. _pThreadPool = NULL;
  1916. _cDesiredOutstanding = 0;
  1917. _cOutstandingContexts = 0;
  1918. _lEnteredOutstandingContextsAddingLoop = 0;
  1919. _pTraceLog = NULL;
  1920. _lNotifyISAPIFilters = 0;
  1921. _pwszFilterChannelName = pwszFilterChannelName;
  1922. _hTimer = NULL;
  1923. _dwTotalFilterChannelContexts = 0;
  1924. };
  1925. //
  1926. // Destructor
  1927. //
  1928. FILTER_CHANNEL::~FILTER_CHANNEL()
  1929. {
  1930. }
  1931. HRESULT
  1932. FILTER_CHANNEL::Initialize(
  1933. VOID
  1934. )
  1935. /*++
  1936. Routine Description:
  1937. Global Initialization
  1938. Arguments:
  1939. None
  1940. Return Value:
  1941. HRESULT
  1942. --*/
  1943. {
  1944. ULONG ulRet = ERROR_SUCCESS;
  1945. HRESULT hr = NO_ERROR;
  1946. BOOL fRet = FALSE;
  1947. HKEY hKeyParam = NULL;
  1948. DWORD dwType = 0;
  1949. DWORD dwValue = 0;
  1950. for ( int i = 0; i < NUM_CS_FILT_CHANNEL_CONTEXTS; i ++ )
  1951. {
  1952. fRet = InitializeCriticalSectionAndSpinCount(
  1953. &_csFiltChannelContexts[ i ],
  1954. 0x80000000 /* precreate event */ |
  1955. IIS_DEFAULT_CS_SPIN_COUNT );
  1956. if ( !fRet )
  1957. {
  1958. hr = HRESULT_FROM_WIN32( GetLastError() );
  1959. goto Finished;
  1960. }
  1961. _dwInitcsFiltChannelContexts ++;
  1962. InitializeListHead( &_ListHead[ i ] );
  1963. InitializeListHead( &_TimerListHead[ i ] );
  1964. }
  1965. #if DBG
  1966. _pTraceLog = CreateRefTraceLog( 2000, 0 );
  1967. #endif
  1968. //
  1969. // Read registry parameters
  1970. //
  1971. if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  1972. REGISTRY_KEY_HTTPFILTER_PARAMETERS_W,
  1973. 0,
  1974. KEY_READ,
  1975. &hKeyParam ) == NO_ERROR )
  1976. {
  1977. DWORD dwBytes = sizeof( dwValue );
  1978. DWORD dwErr = RegQueryValueExW( hKeyParam,
  1979. SZ_REG_DEFAULT_RAW_READ_SIZE,
  1980. NULL,
  1981. &dwType,
  1982. ( LPBYTE )&dwValue,
  1983. &dwBytes
  1984. );
  1985. if ( ( dwErr == ERROR_SUCCESS ) &&
  1986. ( dwType == REG_DWORD ) )
  1987. {
  1988. sm_dwDefaultRawReadSize = dwValue;
  1989. }
  1990. dwBytes = sizeof( dwValue );
  1991. dwErr = RegQueryValueExW( hKeyParam,
  1992. SZ_REG_DEFAULT_APP_READ_SIZE,
  1993. NULL,
  1994. &dwType,
  1995. ( LPBYTE )&dwValue,
  1996. &dwBytes
  1997. );
  1998. if ( ( dwErr == ERROR_SUCCESS ) &&
  1999. ( dwType == REG_DWORD ) )
  2000. {
  2001. // sizeof(HTTP_FILTER_BUFFER) is added because
  2002. // compacted structure HTTP_FILTER_BUFFER is
  2003. // placed to provided buffer
  2004. //
  2005. sm_dwDefaultAppReadSize = dwValue + sizeof( HTTP_FILTER_BUFFER );
  2006. }
  2007. dwBytes = sizeof( dwValue );
  2008. dwErr = RegQueryValueExW( hKeyParam,
  2009. SZ_REG_CONTEXT_DESIRED_OUTSTANDING,
  2010. NULL,
  2011. &dwType,
  2012. ( LPBYTE )&dwValue,
  2013. &dwBytes
  2014. );
  2015. if ( ( dwErr == ERROR_SUCCESS ) &&
  2016. ( dwType == REG_DWORD ) )
  2017. {
  2018. sm_dwContextDesiredOutstanding = dwValue;
  2019. }
  2020. dwBytes = sizeof( dwValue );
  2021. dwErr = RegQueryValueExW( hKeyParam,
  2022. SZ_REG_ENABLE_TEMPORARY_BUFFERS,
  2023. NULL,
  2024. &dwType,
  2025. ( LPBYTE )&dwValue,
  2026. &dwBytes
  2027. );
  2028. if ( ( dwErr == ERROR_SUCCESS ) &&
  2029. ( dwType == REG_DWORD ) )
  2030. {
  2031. sm_fEnableTemporaryBuffers = !!dwValue;
  2032. }
  2033. dwBytes = sizeof( dwValue );
  2034. dwErr = RegQueryValueExW( hKeyParam,
  2035. SZ_RENEGOTIATION_TIMEOUT,
  2036. NULL,
  2037. &dwType,
  2038. ( LPBYTE )&dwValue,
  2039. &dwBytes
  2040. );
  2041. if ( ( dwErr == ERROR_SUCCESS ) &&
  2042. ( dwType == REG_DWORD ) )
  2043. {
  2044. sm_dwHandshakeTimeoutInSec = dwValue;
  2045. if ( sm_dwHandshakeTimeoutInSec > MAXDWORD / 1000 )
  2046. {
  2047. // Disable timers because
  2048. // the configured value is too large
  2049. //
  2050. sm_dwHandshakeTimeoutInSec = 0;
  2051. }
  2052. if ( sm_dwHandshakeTimeoutInSec > 0 &&
  2053. sm_dwHandshakeTimeoutInSec < MINIMUM_RENEGOTIATION_TIMEOUT_IN_SEC )
  2054. {
  2055. //
  2056. // MINIMUM_RENEGOTIATION_TIMEOUT_IN_SEC
  2057. // seconds is minimum for the timeout
  2058. //
  2059. sm_dwHandshakeTimeoutInSec = MINIMUM_RENEGOTIATION_TIMEOUT_IN_SEC;
  2060. }
  2061. }
  2062. RegCloseKey( hKeyParam );
  2063. }
  2064. //
  2065. // Get a UL handle to the RawStreamPool (or whatever)
  2066. //
  2067. ulRet = HttpCreateFilter( &_hFilterHandle,
  2068. _pwszFilterChannelName,
  2069. NULL,
  2070. 0 );
  2071. if ( ulRet != ERROR_SUCCESS )
  2072. {
  2073. //
  2074. // HTTPFilter service may have created Filter already
  2075. // try just open it then
  2076. //
  2077. ulRet = HttpOpenFilter( &_hFilterHandle,
  2078. _pwszFilterChannelName,
  2079. 0 );
  2080. if ( ulRet != ERROR_SUCCESS )
  2081. {
  2082. hr = HRESULT_FROM_WIN32( ulRet );
  2083. goto Finished;
  2084. }
  2085. }
  2086. //
  2087. // Create private thread pool for strmfilt
  2088. //
  2089. THREAD_POOL_CONFIG ThreadPoolConfig;
  2090. SYSTEM_INFO si;
  2091. //
  2092. // we will use GetSystemInfo to retrieve number of processors
  2093. //
  2094. GetSystemInfo( &si );
  2095. hr = InitializeThreadPoolConfigWithDefaults( &ThreadPoolConfig );
  2096. if (FAILED(hr))
  2097. {
  2098. goto Finished;
  2099. }
  2100. //
  2101. // Manual override of some parameters
  2102. //
  2103. // The time (in msecs) of how long the threads can stay alive with no activity
  2104. ThreadPoolConfig.dwThreadTimeout =
  2105. STRMFILT_THREAD_POOL_DEF_THREAD_TIMEOUT * 1000;
  2106. // The number of threads to start
  2107. ThreadPoolConfig.dwInitialThreadCount =
  2108. STRMFILT_THREAD_POOL_DEF_THREAD_COUNT;
  2109. ThreadPoolConfig.dwInitialStackSize =
  2110. IIS_DEFAULT_INITIAL_STACK_SIZE;
  2111. // There is not much blocking on FILTER_CHANNEL execution
  2112. // Performance tests suggested that setting #threads to match
  2113. // # processors is the right thing to do
  2114. // Note: There are cases where soft thread limit is bumped up
  2115. // such as before AcceptSecurityContext() when hardware
  2116. // accelerator is used
  2117. //
  2118. // we need miminum of 2 threads because current thread pool manager implementation
  2119. // will not allow to add new threads when soft thread limit is incremented
  2120. //
  2121. ThreadPoolConfig.dwSoftLimitThreadCount = max( 2, si.dwNumberOfProcessors );
  2122. //
  2123. // Override threadpool settings with registry values (if configured)
  2124. //
  2125. hr = OverrideThreadPoolConfigWithRegistry( &ThreadPoolConfig,
  2126. REGISTRY_KEY_HTTPFILTER_PARAMETERS_W );
  2127. if (FAILED(hr))
  2128. {
  2129. goto Finished;
  2130. }
  2131. fRet = THREAD_POOL::CreateThreadPool( &_pThreadPool,
  2132. &ThreadPoolConfig );
  2133. if ( !fRet )
  2134. {
  2135. DBGPRINTF(( DBG_CONTEXT,
  2136. "Failed to create ThreadPool for Strmfilt\n" ));
  2137. hr = E_FAIL;
  2138. goto Finished;
  2139. }
  2140. DBG_ASSERT( _pThreadPool != NULL );
  2141. //
  2142. // Associate a completion routine with the thread pool
  2143. //
  2144. DBG_ASSERT( _hFilterHandle != INVALID_HANDLE_VALUE );
  2145. DBG_ASSERT( _hFilterHandle != NULL );
  2146. if ( !_pThreadPool->BindIoCompletionCallback(_hFilterHandle,
  2147. OverlappedCompletionRoutine,
  2148. 0 ) )
  2149. {
  2150. hr = HRESULT_FROM_WIN32( GetLastError() );
  2151. goto Finished;
  2152. }
  2153. //
  2154. // Keep a set number of filter accepts outstanding
  2155. //
  2156. _cDesiredOutstanding = sm_dwContextDesiredOutstanding;
  2157. //
  2158. // If sm_dwHandshakeTimeoutInSec == 0 then timers are disabled
  2159. //
  2160. if ( sm_dwHandshakeTimeoutInSec != 0 )
  2161. {
  2162. fRet = CreateTimerQueueTimer(
  2163. &_hTimer,
  2164. NULL,
  2165. FILTER_CHANNEL::TimerCallback,
  2166. this,
  2167. (( sm_dwHandshakeTimeoutInSec / 2 )) * 1000,
  2168. (( sm_dwHandshakeTimeoutInSec / 2 )) * 1000,
  2169. WT_EXECUTELONGFUNCTION );
  2170. if ( !fRet )
  2171. {
  2172. hr = HRESULT_FROM_WIN32( GetLastError() );
  2173. goto Finished;
  2174. }
  2175. }
  2176. Finished:
  2177. if ( FAILED( hr ) )
  2178. {
  2179. FILTER_CHANNEL::Terminate();
  2180. }
  2181. return hr;
  2182. }
  2183. VOID
  2184. FILTER_CHANNEL::Terminate(
  2185. VOID
  2186. )
  2187. /*++
  2188. Routine Description:
  2189. Global termination
  2190. Arguments:
  2191. None
  2192. Return Value:
  2193. None
  2194. --*/
  2195. {
  2196. //
  2197. // Thread pool must be terminated before any other objects get cleaned up
  2198. // to assure that there are no worker threads still executing
  2199. //
  2200. if ( _hTimer != NULL )
  2201. {
  2202. DeleteTimerQueueTimer(
  2203. NULL, //use default timer queue
  2204. _hTimer,
  2205. INVALID_HANDLE_VALUE /*wait for completion of the callback*/);
  2206. _hTimer = NULL;
  2207. }
  2208. if ( _pThreadPool != NULL )
  2209. {
  2210. _pThreadPool->TerminateThreadPool();
  2211. _pThreadPool = NULL;
  2212. }
  2213. if ( _hFilterHandle != NULL )
  2214. {
  2215. CloseHandle( _hFilterHandle );
  2216. _hFilterHandle = NULL;
  2217. }
  2218. if ( _pTraceLog != NULL )
  2219. {
  2220. DestroyRefTraceLog( _pTraceLog );
  2221. _pTraceLog = NULL;
  2222. }
  2223. for ( int i = 0; i < _dwInitcsFiltChannelContexts; i ++ )
  2224. {
  2225. DeleteCriticalSection( &_csFiltChannelContexts[ i ] );
  2226. }
  2227. _dwInitcsFiltChannelContexts = 0;
  2228. };
  2229. VOID
  2230. FILTER_CHANNEL::InsertFiltChannelContext(
  2231. FILTER_CHANNEL_CONTEXT *pFiltChannelContext
  2232. )
  2233. {
  2234. DWORD dwFilterContextCount = (DWORD)
  2235. InterlockedIncrement( (PLONG) &_dwTotalFilterChannelContexts );
  2236. //
  2237. // Determine which lock, sublist will be used for this context
  2238. // Use round robin
  2239. //
  2240. DWORD dwLockIndex = dwFilterContextCount % NUM_CS_FILT_CHANNEL_CONTEXTS;
  2241. pFiltChannelContext->SetLockIndex( dwLockIndex );
  2242. EnterCriticalSection( &_csFiltChannelContexts[ dwLockIndex ] );
  2243. InsertHeadList( &_ListHead[ dwLockIndex ], &pFiltChannelContext->_ListEntry );
  2244. //
  2245. // We have to interlocked increment the _cFiltChannelContexts
  2246. // because the the lock we acquired
  2247. // is only the lock to a sublist of contexts so there may be
  2248. // multiple concurrent attempts to increment _cFiltChannelContexts
  2249. //
  2250. InterlockedIncrement( (LONG *)&_cFiltChannelContexts );
  2251. LeaveCriticalSection( &_csFiltChannelContexts[ dwLockIndex ] );
  2252. }
  2253. VOID
  2254. FILTER_CHANNEL::RemoveFiltChannelContext(
  2255. FILTER_CHANNEL_CONTEXT *pFiltChannelContext
  2256. )
  2257. {
  2258. DWORD dwLockIndex = pFiltChannelContext->QueryLockIndex();
  2259. EnterCriticalSection( &_csFiltChannelContexts[ dwLockIndex ] );
  2260. InterlockedDecrement( (LONG *)&_cFiltChannelContexts );
  2261. RemoveEntryList( &pFiltChannelContext->_ListEntry );
  2262. LeaveCriticalSection( &_csFiltChannelContexts[ dwLockIndex ] );
  2263. }
  2264. VOID
  2265. FILTER_CHANNEL::InsertFiltChannelContextToTimerList(
  2266. FILTER_CHANNEL_CONTEXT *pFiltChannelContext
  2267. )
  2268. /*++
  2269. Routine Description:
  2270. Add context to the timeout timer list
  2271. Arguments:
  2272. pFiltChannelContext - context to be added to the timeout timer list
  2273. Return Value:
  2274. None
  2275. --*/
  2276. {
  2277. DWORD dwCurrentTickCount = GetTickCount();
  2278. if ( sm_dwHandshakeTimeoutInSec == 0 )
  2279. {
  2280. //
  2281. // timeouts are disabled
  2282. //
  2283. return;
  2284. }
  2285. DWORD dwLockIndex = pFiltChannelContext->QueryLockIndex();
  2286. EnterCriticalSection( &_csFiltChannelContexts[ dwLockIndex ] );
  2287. if ( pFiltChannelContext->QueryIsAlreadyOnTimerList() )
  2288. {
  2289. // Entry already on the list but
  2290. // tickCount for the entry will be updated
  2291. // We have to remove entry from the current position
  2292. // so that it can be added to the end since
  2293. // the list is ordered by the TickCounts
  2294. //
  2295. RemoveEntryList( &pFiltChannelContext->_TimerListEntry );
  2296. }
  2297. //
  2298. // New entries go to the end of the list
  2299. //
  2300. InsertTailList( &_TimerListHead[ dwLockIndex ], &pFiltChannelContext->_TimerListEntry );
  2301. pFiltChannelContext->SetTimerTickCount( dwCurrentTickCount );
  2302. LeaveCriticalSection( &_csFiltChannelContexts[ dwLockIndex ] );
  2303. }
  2304. VOID
  2305. FILTER_CHANNEL::RemoveFiltChannelContextFromTimerList(
  2306. FILTER_CHANNEL_CONTEXT *pFiltChannelContext
  2307. )
  2308. {
  2309. /*++
  2310. Routine Description:
  2311. Remove context from the timeout timer list
  2312. Arguments:
  2313. pFiltChannelContext - context to be removed from the timeout timer list
  2314. Return Value:
  2315. None
  2316. --*/
  2317. DWORD dwLockIndex = pFiltChannelContext->QueryLockIndex();
  2318. EnterCriticalSection( &_csFiltChannelContexts[ dwLockIndex ] );
  2319. RemoveEntryList( &pFiltChannelContext->_TimerListEntry );
  2320. pFiltChannelContext->ResetTimerTickCount();
  2321. LeaveCriticalSection( &_csFiltChannelContexts[ dwLockIndex ] );
  2322. }
  2323. VOID
  2324. FILTER_CHANNEL::WaitForContextDrain(
  2325. VOID
  2326. )
  2327. /*++
  2328. Routine Description:
  2329. Wait for all contexts to go away
  2330. Arguments:
  2331. None
  2332. Return Value:
  2333. None
  2334. --*/
  2335. {
  2336. while ( _cFiltChannelContexts != 0 )
  2337. {
  2338. DBGPRINTF(( DBG_CONTEXT,
  2339. "Waiting for %d CONTEXTs for %S to drain\n",
  2340. _cFiltChannelContexts,
  2341. _pwszFilterChannelName ));
  2342. Sleep( 1000 );
  2343. }
  2344. //
  2345. // there should be no outstanding contexts left
  2346. //
  2347. DBG_ASSERT( _cOutstandingContexts == 0 );
  2348. }
  2349. HRESULT
  2350. FILTER_CHANNEL::StartListening(
  2351. VOID
  2352. )
  2353. /*++
  2354. Routine Description:
  2355. Start listening - create initial UL_CONTEXTs
  2356. Arguments:
  2357. None
  2358. Return Value:
  2359. HRESULT
  2360. --*/
  2361. {
  2362. HRESULT hr = ManageOutstandingContexts();
  2363. if ( SUCCEEDED( hr ) )
  2364. {
  2365. InterlockedExchange( &_lStartedListening, 1 );
  2366. }
  2367. return hr;
  2368. }
  2369. VOID
  2370. FILTER_CHANNEL::StopListening(
  2371. VOID
  2372. )
  2373. /*++
  2374. Routine Description:
  2375. Stop listening and wait for contexts to drain
  2376. Arguments:
  2377. None
  2378. Return Value:
  2379. None
  2380. --*/
  2381. {
  2382. DBG_REQUIRE( HttpShutdownFilter( _hFilterHandle ) == ERROR_SUCCESS );
  2383. InterlockedExchange(&_lStartedListening, 0 );
  2384. WaitForContextDrain();
  2385. }
  2386. //
  2387. // Keep enough UL_CONTEXTs listening
  2388. //
  2389. HRESULT
  2390. FILTER_CHANNEL::ManageOutstandingContexts(
  2391. VOID
  2392. )
  2393. /*++
  2394. Routine Description:
  2395. add sufficient number of new contexts
  2396. Arguments:
  2397. None
  2398. Return Value:
  2399. HRESULT
  2400. --*/
  2401. {
  2402. LONG cRequired;
  2403. FILTER_CHANNEL_CONTEXT * pContext;
  2404. HRESULT hr = NO_ERROR;
  2405. if ( _cOutstandingContexts < _cDesiredOutstanding )
  2406. {
  2407. cRequired = _cDesiredOutstanding - _cOutstandingContexts;
  2408. //
  2409. // Make sure the value is not negative
  2410. //
  2411. cRequired = max( 0, cRequired );
  2412. for ( LONG i = 0; i < cRequired; i++ )
  2413. {
  2414. hr = CreateContext( &pContext );
  2415. if ( FAILED( hr ) )
  2416. {
  2417. break;
  2418. }
  2419. DBG_ASSERT( pContext );
  2420. hr = pContext->DoAccept();
  2421. if ( FAILED( hr ) )
  2422. {
  2423. pContext->DereferenceFiltChannelContext();
  2424. break;
  2425. }
  2426. }
  2427. }
  2428. return hr;
  2429. }
  2430. HRESULT
  2431. FILTER_CHANNEL::DecrementAndManageOutstandingContexts(
  2432. VOID
  2433. )
  2434. /*++
  2435. Routine Description:
  2436. Decrement available outstanding Context and
  2437. add sufficient number of new contexts
  2438. Arguments:
  2439. None
  2440. Return Value:
  2441. HRESULT
  2442. --*/
  2443. {
  2444. HRESULT hr = E_FAIL;
  2445. LONG lPreviousContexts =
  2446. InterlockedDecrement( &_cOutstandingContexts );
  2447. if ( _lStartedListening == 1 )
  2448. {
  2449. hr = ManageOutstandingContexts();
  2450. if ( FAILED(hr) &&
  2451. lPreviousContexts == 1 )
  2452. {
  2453. //
  2454. // If there are no outstanding contexts
  2455. // strmfilt will not be able to accept new connections
  2456. // Keep retrying until we succeed
  2457. // or until service get's shut down
  2458. //
  2459. // Note: this loop will be blocking processing
  2460. // the completion of the new connection but if
  2461. // we hit problems with adding new outstanding context
  2462. // that is big enough problem so we can afford
  2463. // to sacrifise this one connection until
  2464. // adding of new outstanding contexts succeeds
  2465. LONG lOldValue = InterlockedExchange(
  2466. &_lEnteredOutstandingContextsAddingLoop,
  2467. 1 );
  2468. //
  2469. // Let's have only one thread trying to add
  2470. // outstanding contexts to minimize impact on system
  2471. // (in low memory or similar condition - under normal
  2472. // circumstances contexts should have no problems to be added)
  2473. //
  2474. if ( lOldValue == 0 )
  2475. {
  2476. //
  2477. // if lOldValue = 0 it means we are the first thread trying
  2478. //
  2479. do
  2480. {
  2481. Sleep( 2000 );
  2482. hr = ManageOutstandingContexts();
  2483. }while( FAILED( hr ) && _lStartedListening == 1 );
  2484. InterlockedExchange(
  2485. &_lEnteredOutstandingContextsAddingLoop,
  2486. 0 );
  2487. }
  2488. }
  2489. }
  2490. return hr;
  2491. }
  2492. HRESULT
  2493. FILTER_CHANNEL::EnableISAPIFilters(
  2494. ISAPI_FILTERS_CALLBACKS * pConfig
  2495. )
  2496. /*++
  2497. Routine Description:
  2498. enable ISAPI Filters
  2499. ( all new connections will notify ISAPI Filters )
  2500. Arguments:
  2501. pStreamConfig - config info
  2502. Return Value:
  2503. HRESULT
  2504. --*/
  2505. {
  2506. HRESULT hr = E_FAIL;
  2507. hr = ISAPI_STREAM_CONTEXT::EnableISAPIFilters( pConfig );
  2508. if ( FAILED( hr ) )
  2509. {
  2510. return hr;
  2511. }
  2512. SetNotifyISAPIFilters( TRUE );
  2513. return S_OK;
  2514. }
  2515. VOID
  2516. FILTER_CHANNEL::DisableISAPIFilters(
  2517. VOID
  2518. )
  2519. /*++
  2520. Routine Description:
  2521. safely terminate ISAPI Filters
  2522. ( all connections with ISAPI Filters must be closed )
  2523. Arguments:
  2524. None
  2525. Return Value:
  2526. None
  2527. --*/
  2528. {
  2529. //
  2530. // stop notifying ISAPI Filters
  2531. //
  2532. SetNotifyISAPIFilters( FALSE );
  2533. ISAPI_STREAM_CONTEXT::DisableISAPIFilters();
  2534. }
  2535. //static
  2536. VOID
  2537. WINAPI
  2538. FILTER_CHANNEL::TimerCallback(
  2539. PVOID pParam,
  2540. BOOLEAN
  2541. )
  2542. /*++
  2543. Routine Description:
  2544. Close all the connections that have timed out based on the
  2545. timer settings
  2546. Arguments:
  2547. None
  2548. Return Value:
  2549. None
  2550. --*/
  2551. {
  2552. //
  2553. // slTimerCallbackEntryCount will guard against the case
  2554. // where new timer callback comes in when the previous is still
  2555. // executing
  2556. //
  2557. static LONG slTimerCallbackEntryCount = 0;
  2558. if ( InterlockedIncrement (&slTimerCallbackEntryCount ) != 1 )
  2559. {
  2560. InterlockedDecrement ( &slTimerCallbackEntryCount );
  2561. return;
  2562. }
  2563. DWORD dwCurrentTickCount = GetTickCount();
  2564. DBG_ASSERT( pParam != NULL );
  2565. FILTER_CHANNEL * pFilterChannel = reinterpret_cast<FILTER_CHANNEL *>( pParam );
  2566. // Filter channel Context lock is split to minimize scaling problems
  2567. //
  2568. for ( int dwLockIndex = 0; dwLockIndex < NUM_CS_FILT_CHANNEL_CONTEXTS;
  2569. dwLockIndex ++ )
  2570. {
  2571. EnterCriticalSection( &pFilterChannel->_csFiltChannelContexts[ dwLockIndex ] );
  2572. while ( !IsListEmpty ( &pFilterChannel->_TimerListHead [ dwLockIndex ] ) )
  2573. {
  2574. LIST_ENTRY *pCurrentEntry =
  2575. pFilterChannel->_TimerListHead[ dwLockIndex ].Flink;
  2576. FILTER_CHANNEL_CONTEXT * pFiltChannelContext =
  2577. CONTAINING_RECORD( pCurrentEntry,
  2578. FILTER_CHANNEL_CONTEXT,
  2579. _TimerListEntry );
  2580. DBG_ASSERT( pFiltChannelContext->CheckSignature() );
  2581. DWORD dwElapsedTimeInMSec;
  2582. if ( dwCurrentTickCount < pFiltChannelContext->QueryTimerTickCount() )
  2583. {
  2584. //
  2585. // Wrap around
  2586. //
  2587. dwElapsedTimeInMSec = MAXDWORD - dwCurrentTickCount +
  2588. pFiltChannelContext->QueryTimerTickCount();
  2589. }
  2590. else
  2591. {
  2592. dwElapsedTimeInMSec = dwCurrentTickCount -
  2593. pFiltChannelContext->QueryTimerTickCount();
  2594. }
  2595. if ( dwElapsedTimeInMSec < sm_dwHandshakeTimeoutInSec * 1000 )
  2596. {
  2597. //
  2598. // all the subsequent entries are newer the the current one
  2599. // so we can safely assume that neither of them needs to
  2600. // expire at this point
  2601. //
  2602. break;
  2603. }
  2604. //
  2605. // It is time to request closing the connection
  2606. //
  2607. pFilterChannel->RemoveFiltChannelContextFromTimerList(
  2608. pFiltChannelContext );
  2609. //
  2610. // Note: Do not use pFilterChannelContext passed the StartClose()
  2611. // because it will not be guaranteed to be around any more
  2612. //
  2613. // Note2: StartClose() may reentrantly acquire the
  2614. // pFilterChannel->_csFiltChannelContexts lock if destructor
  2615. // happens to be called on FiltChannelContext dereference
  2616. // inside the StartClose()
  2617. pFiltChannelContext->StartClose();
  2618. }
  2619. LeaveCriticalSection( &pFilterChannel->_csFiltChannelContexts[ dwLockIndex ] );
  2620. }
  2621. InterlockedDecrement ( &slTimerCallbackEntryCount );
  2622. }
  2623. SSL_SERVER_FILTER_CHANNEL_CONTEXT::SSL_SERVER_FILTER_CHANNEL_CONTEXT(
  2624. SSL_SERVER_FILTER_CHANNEL *pManager
  2625. )
  2626. : FILTER_CHANNEL_CONTEXT(pManager)
  2627. {
  2628. _dwSignature = SSL_SERVER_FILTER_CHANNEL_CONTEXT_SIGNATURE;
  2629. }
  2630. SSL_SERVER_FILTER_CHANNEL_CONTEXT::~SSL_SERVER_FILTER_CHANNEL_CONTEXT()
  2631. {
  2632. _dwSignature = SSL_SERVER_FILTER_CHANNEL_CONTEXT_SIGNATURE_FREE;
  2633. }
  2634. //static
  2635. HRESULT
  2636. SSL_SERVER_FILTER_CHANNEL_CONTEXT::Initialize(
  2637. VOID
  2638. )
  2639. /*++
  2640. Routine Description:
  2641. Global initialization routine for FILTER_CHANNEL_CONTEXT
  2642. Arguments:
  2643. None
  2644. Return Value:
  2645. HRESULT
  2646. --*/
  2647. {
  2648. ALLOC_CACHE_CONFIGURATION acConfig;
  2649. //
  2650. // Setup allocation lookaside
  2651. //
  2652. acConfig.nConcurrency = 1;
  2653. acConfig.nThreshold = 100;
  2654. acConfig.cbSize = sizeof( SSL_SERVER_FILTER_CHANNEL_CONTEXT );
  2655. DBG_ASSERT( sm_pachFilterChannelContexts == NULL );
  2656. sm_pachFilterChannelContexts = new ALLOC_CACHE_HANDLER( "SSL_SERVER_FILTER_CHANNEL_CONTEXT",
  2657. &acConfig );
  2658. if ( sm_pachFilterChannelContexts == NULL )
  2659. {
  2660. return HRESULT_FROM_WIN32( ERROR_NOT_ENOUGH_MEMORY );
  2661. }
  2662. return NO_ERROR;
  2663. }
  2664. //static
  2665. VOID
  2666. SSL_SERVER_FILTER_CHANNEL_CONTEXT::Terminate(
  2667. VOID
  2668. )
  2669. /*++
  2670. Routine Description:
  2671. Terminate FILTER_CHANNEL_CONTEXT globals
  2672. Arguments:
  2673. None
  2674. Return Value:
  2675. None
  2676. --*/
  2677. {
  2678. if ( sm_pachFilterChannelContexts != NULL )
  2679. {
  2680. delete sm_pachFilterChannelContexts;
  2681. sm_pachFilterChannelContexts = NULL;
  2682. }
  2683. }
  2684. HRESULT
  2685. SSL_SERVER_FILTER_CHANNEL_CONTEXT::Create(
  2686. VOID
  2687. )
  2688. /*++
  2689. Routine Description:
  2690. Initialize a SSL_SERVER_FILTER_CHANNEL_CONTEXT
  2691. Arguments:
  2692. None
  2693. Return Value:
  2694. HRESULT
  2695. --*/
  2696. {
  2697. DBG_ASSERT( _pSSLContext == NULL );
  2698. DBG_ASSERT( _pISAPIContext == NULL );
  2699. _pSSLContext = new SSL_STREAM_CONTEXT( this );
  2700. if ( _pSSLContext == NULL )
  2701. {
  2702. return HRESULT_FROM_WIN32( GetLastError() );
  2703. }
  2704. return NO_ERROR;
  2705. }
  2706. VOID
  2707. OverlappedCompletionRoutine(
  2708. DWORD dwErrorCode,
  2709. DWORD dwNumberOfBytesTransfered,
  2710. LPOVERLAPPED lpOverlapped
  2711. )
  2712. /*++
  2713. Routine Description:
  2714. Magic completion routine
  2715. Arguments:
  2716. None
  2717. Return Value:
  2718. None
  2719. --*/
  2720. {
  2721. UL_OVERLAPPED_CONTEXT * pContextOverlapped = NULL;
  2722. HRESULT hr;
  2723. FILTER_CHANNEL_CONTEXT * pFiltChannelContext = NULL;
  2724. DBG_ASSERT( lpOverlapped != NULL );
  2725. pContextOverlapped =
  2726. UL_OVERLAPPED_CONTEXT::GetUlOverlappedContext( lpOverlapped );
  2727. DBG_ASSERT( pContextOverlapped != NULL );
  2728. //
  2729. // pFiltChannelContext was referenced in the Async Read/Write call
  2730. // Reference is still held and it is safe to access the object
  2731. // Completion routines will release the reference
  2732. //
  2733. pFiltChannelContext = pContextOverlapped->QueryContext();
  2734. //
  2735. // Call the appropriate completion routine
  2736. //
  2737. //
  2738. // Note: Completion routines may delete UL_OVERLAPPED_CONTEXT
  2739. // at least OnRawWriteCompletion() deletes temporary contexts
  2740. // Do not use pContextOverlapped after CompletionRoutines were called
  2741. //
  2742. switch( pContextOverlapped->QueryType() )
  2743. {
  2744. case UL_OVERLAPPED_CONTEXT_RAW_READ:
  2745. IF_DEBUG( APP_RAW_READWRITE )
  2746. {
  2747. DBGPRINTF(( DBG_CONTEXT,
  2748. "ENTER OnRawReadCompletion( bytes:%d, dwErr:%d )\n",
  2749. dwNumberOfBytesTransfered,
  2750. dwErrorCode
  2751. ));
  2752. }
  2753. hr = pFiltChannelContext->OnRawReadCompletion( dwNumberOfBytesTransfered,
  2754. dwErrorCode );
  2755. IF_DEBUG( APP_RAW_READWRITE )
  2756. {
  2757. DBGPRINTF(( DBG_CONTEXT,
  2758. "LEAVE OnRawReadCompletion( bytes:%d, dwErr:%d ) hr=0x%x\n",
  2759. dwNumberOfBytesTransfered,
  2760. dwErrorCode,
  2761. hr
  2762. ));
  2763. }
  2764. break;
  2765. case UL_OVERLAPPED_CONTEXT_RAW_WRITE:
  2766. IF_DEBUG( APP_RAW_READWRITE )
  2767. {
  2768. DBGPRINTF(( DBG_CONTEXT,
  2769. "ENTER OnRawWriteCompletion( bytes:%d, dwErr:%d )\n",
  2770. dwNumberOfBytesTransfered,
  2771. dwErrorCode
  2772. ));
  2773. }
  2774. hr = pFiltChannelContext->OnRawWriteCompletion( dwNumberOfBytesTransfered,
  2775. dwErrorCode,
  2776. pContextOverlapped );
  2777. IF_DEBUG( APP_RAW_READWRITE )
  2778. {
  2779. DBGPRINTF(( DBG_CONTEXT,
  2780. "LEAVE OnRawWriteCompletion( bytes:%d, dwErr:%d ) hr=0x%x\n",
  2781. dwNumberOfBytesTransfered,
  2782. dwErrorCode,
  2783. hr
  2784. ));
  2785. }
  2786. break;
  2787. case UL_OVERLAPPED_CONTEXT_APP_READ:
  2788. IF_DEBUG( APP_RAW_READWRITE )
  2789. {
  2790. DBGPRINTF(( DBG_CONTEXT,
  2791. "ENTER OnAppReadCompletion( bytes:%d, dwErr:%d )\n",
  2792. dwNumberOfBytesTransfered,
  2793. dwErrorCode
  2794. ));
  2795. }
  2796. hr = pFiltChannelContext->OnAppReadCompletion( dwNumberOfBytesTransfered,
  2797. dwErrorCode );
  2798. IF_DEBUG( APP_RAW_READWRITE )
  2799. {
  2800. DBGPRINTF(( DBG_CONTEXT,
  2801. "LEAVE OnAppReadCompletion ( bytes:%d, dwErr:%d ) hr=0x%x\n",
  2802. dwNumberOfBytesTransfered,
  2803. dwErrorCode,
  2804. hr
  2805. ));
  2806. }
  2807. break;
  2808. case UL_OVERLAPPED_CONTEXT_APP_WRITE:
  2809. IF_DEBUG( APP_RAW_READWRITE )
  2810. {
  2811. DBGPRINTF(( DBG_CONTEXT,
  2812. "ENTER OnAppWriteCompletion( bytes:%d, dwErr:%d )\n",
  2813. dwNumberOfBytesTransfered,
  2814. dwErrorCode
  2815. ));
  2816. }
  2817. hr = pFiltChannelContext->OnAppWriteCompletion( dwNumberOfBytesTransfered,
  2818. dwErrorCode );
  2819. IF_DEBUG( APP_RAW_READWRITE )
  2820. {
  2821. DBGPRINTF(( DBG_CONTEXT,
  2822. "LEAVE OnAppWriteCompletion( bytes:%d, dwErr:%d ) hr=0x%x\n",
  2823. dwNumberOfBytesTransfered,
  2824. dwErrorCode,
  2825. hr
  2826. ));
  2827. }
  2828. break;
  2829. case UL_OVERLAPPED_CONTEXT_CLOSE:
  2830. IF_DEBUG( APP_RAW_READWRITE )
  2831. {
  2832. DBGPRINTF(( DBG_CONTEXT,
  2833. "Connection close completed (there still may be outstanding I/Os unless the refcount is 1)\n"
  2834. ));
  2835. }
  2836. //
  2837. // Closing the connection was completed
  2838. // Notify whoever is interested
  2839. //
  2840. pFiltChannelContext->CloseNotify();
  2841. //
  2842. // Do the final dereference
  2843. //
  2844. pFiltChannelContext->DereferenceFiltChannelContext();
  2845. break;
  2846. default:
  2847. hr = HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  2848. DBG_ASSERT( FALSE );
  2849. }
  2850. pFiltChannelContext = NULL;
  2851. // Reference on the context was released in completion routine
  2852. // don't use it past this point
  2853. }