Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1943 lines
45 KiB

  1. /*++
  2. Copyright (c) 1999 Microsoft Corporation
  3. Module Name :
  4. rawconnection.cxx
  5. Abstract:
  6. ISAPI raw data filter support
  7. Author:
  8. Bilal Alam (balam) 10-Jan-2000
  9. Environment:
  10. Win32 - User Mode
  11. Project:
  12. ULW3.DLL
  13. --*/
  14. #include "precomp.hxx"
  15. #include "rawconnection.hxx"
  16. RAW_CONNECTION_HASH * RAW_CONNECTION::sm_pRawConnectionHash;
  17. RAW_CONNECTION::RAW_CONNECTION(
  18. CONNECTION_INFO * pConnectionInfo
  19. )
  20. {
  21. _cRefs = 1;
  22. _pMainContext = NULL;
  23. _dwCurrentFilter = INVALID_DLL;
  24. DBG_ASSERT( pConnectionInfo != NULL );
  25. _hfc.cbSize = sizeof( _hfc );
  26. _hfc.Revision = HTTP_FILTER_REVISION;
  27. _hfc.ServerContext = (void *) this;
  28. _hfc.ulReserved = 0;
  29. _hfc.fIsSecurePort = pConnectionInfo->fIsSecure;
  30. _hfc.pFilterContext = NULL;
  31. _hfc.ServerSupportFunction = RawFilterServerSupportFunction;
  32. _hfc.GetServerVariable = RawFilterGetServerVariable;
  33. _hfc.AddResponseHeaders = RawFilterAddResponseHeaders;
  34. _hfc.WriteClient = RawFilterWriteClient;
  35. _hfc.AllocMem = RawFilterAllocateMemory;
  36. ZeroMemory( &_rgContexts, sizeof( _rgContexts ) );
  37. InitializeListHead( &_PoolHead );
  38. _pfnSendDataBack = pConnectionInfo->pfnSendDataBack;
  39. _pvStreamContext = pConnectionInfo->pvStreamContext;
  40. _LocalPort = pConnectionInfo->LocalPort;
  41. _LocalAddress = pConnectionInfo->LocalAddress;
  42. _RemotePort = pConnectionInfo->RemotePort;
  43. _RemoteAddress = pConnectionInfo->RemoteAddress;
  44. _RawConnectionId = pConnectionInfo->RawConnectionId;
  45. _dwSignature = RAW_CONNECTION_SIGNATURE;
  46. }
  47. RAW_CONNECTION::~RAW_CONNECTION()
  48. {
  49. FILTER_POOL_ITEM * pfpi;
  50. _dwSignature = RAW_CONNECTION_SIGNATURE_FREE;
  51. //
  52. // Free pool items (is most cases there won't be any since they will
  53. // have been migrated to the W3_FILTER_CONNECTION_CONTEXT)
  54. //
  55. while ( !IsListEmpty( &_PoolHead ) )
  56. {
  57. pfpi = CONTAINING_RECORD( _PoolHead.Flink,
  58. FILTER_POOL_ITEM,
  59. _ListEntry );
  60. RemoveEntryList( &pfpi->_ListEntry );
  61. delete pfpi;
  62. }
  63. //
  64. // Disconnect raw connection from main context
  65. //
  66. if ( _pMainContext != NULL )
  67. {
  68. _pMainContext->DereferenceMainContext();
  69. _pMainContext = NULL;
  70. }
  71. }
  72. //static
  73. HRESULT
  74. RAW_CONNECTION::Initialize(
  75. VOID
  76. )
  77. /*++
  78. Routine Description:
  79. Initialize ISAPI raw data filter crap
  80. Arguments:
  81. None
  82. Return Value:
  83. HRESULT
  84. --*/
  85. {
  86. FILTER_LIST * pFilterList;
  87. BOOL fSSLOnly = TRUE;
  88. HRESULT hr;
  89. STREAM_FILTER_CONFIG sfConfig;
  90. DBG_ASSERT( g_pW3Server != NULL );
  91. DBG_ASSERT( sm_pRawConnectionHash == NULL );
  92. //
  93. // Create a UL_RAW_CONNECTION_ID keyed hash table
  94. //
  95. sm_pRawConnectionHash = new RAW_CONNECTION_HASH;
  96. if ( sm_pRawConnectionHash == NULL )
  97. {
  98. return HRESULT_FROM_WIN32( GetLastError() );
  99. }
  100. //
  101. // Is there a read raw data filter enabled?
  102. //
  103. pFilterList = FILTER_LIST::QueryGlobalList();
  104. if ( pFilterList != NULL )
  105. {
  106. if ( pFilterList->IsNotificationNeeded( SF_NOTIFY_READ_RAW_DATA,
  107. FALSE ) )
  108. {
  109. fSSLOnly = FALSE;
  110. }
  111. }
  112. //
  113. // Now initialize stream filter DLL
  114. //
  115. sfConfig.fSslOnly = fSSLOnly;
  116. sfConfig.pfnRawRead = RAW_CONNECTION::ProcessRawRead;
  117. sfConfig.pfnRawWrite = RAW_CONNECTION::ProcessRawWrite;
  118. sfConfig.pfnConnectionClose = RAW_CONNECTION::ProcessConnectionClose;
  119. sfConfig.pfnNewConnection = RAW_CONNECTION::ProcessNewConnection;
  120. hr = StreamFilterInitialize( &sfConfig );
  121. if ( FAILED( hr ) )
  122. {
  123. delete sm_pRawConnectionHash;
  124. sm_pRawConnectionHash = NULL;
  125. return hr;
  126. }
  127. return NO_ERROR;
  128. }
  129. //static
  130. VOID
  131. RAW_CONNECTION::Terminate(
  132. VOID
  133. )
  134. /*++
  135. Routine Description:
  136. Terminate raw connection hash table
  137. Arguments:
  138. None
  139. Return Value:
  140. None
  141. --*/
  142. {
  143. StreamFilterTerminate();
  144. if ( sm_pRawConnectionHash != NULL )
  145. {
  146. delete sm_pRawConnectionHash;
  147. sm_pRawConnectionHash = NULL;
  148. }
  149. }
  150. //static
  151. HRESULT
  152. RAW_CONNECTION::StopListening(
  153. VOID
  154. )
  155. /*++
  156. Routine Description:
  157. Begin shutdown by preventing further raw stream messages from UL
  158. Arguments:
  159. None
  160. Return Value:
  161. HRESULT
  162. --*/
  163. {
  164. StreamFilterStop();
  165. return NO_ERROR;
  166. }
  167. //static
  168. HRESULT
  169. RAW_CONNECTION::StartListening(
  170. VOID
  171. )
  172. /*++
  173. Routine Description:
  174. Start listening for stream messages from UL. Unlike UlAtqStartListen(),
  175. this routine does NOT block and will return once the initial number
  176. of outstanding UlFilterAccept() requests have been made
  177. Arguments:
  178. None
  179. Return Value:
  180. HRESULT
  181. --*/
  182. {
  183. return StreamFilterStart();
  184. }
  185. FILTER_LIST *
  186. RAW_CONNECTION::QueryFilterList(
  187. VOID
  188. )
  189. /*++
  190. Routine Description:
  191. Return the appropriate filter list to notify. Before a W3_CONNECTION
  192. is established, this list will simply be the global filter list. But
  193. once the W3_CONNECTION is established, the list will be the appropriate
  194. instance filter list
  195. Arguments:
  196. None
  197. Return Value:
  198. FILTER_LIST *
  199. --*/
  200. {
  201. W3_FILTER_CONTEXT * pFilterContext = NULL;
  202. FILTER_LIST * pFilterList = FILTER_LIST::QueryGlobalList();
  203. if ( _pMainContext != NULL )
  204. {
  205. pFilterContext = _pMainContext->QueryFilterContext();
  206. if ( pFilterContext != NULL )
  207. {
  208. pFilterList = pFilterContext->QueryFilterList();
  209. DBG_ASSERT( pFilterList != NULL );
  210. }
  211. }
  212. return pFilterList;
  213. }
  214. BOOL
  215. RAW_CONNECTION::QueryNotificationChanged(
  216. VOID
  217. )
  218. /*++
  219. Routine Description:
  220. Returns whether or not any notifications have been disabled on the fly
  221. Arguments:
  222. None
  223. Return Value:
  224. BOOL
  225. --*/
  226. {
  227. W3_FILTER_CONTEXT * pFilterContext;
  228. if ( _pMainContext == NULL )
  229. {
  230. //
  231. // BUGBUG
  232. //
  233. // This isn't totally correct. I guess a read raw filter could
  234. // disable any more notifications for itself before a
  235. // W3_CONNECTION is created. This is really corner
  236. //
  237. return FALSE;
  238. }
  239. else
  240. {
  241. pFilterContext = _pMainContext->QueryFilterContext();
  242. if ( pFilterContext == NULL )
  243. {
  244. return FALSE;
  245. }
  246. else
  247. {
  248. return pFilterContext->QueryNotificationChanged();
  249. }
  250. }
  251. }
  252. BOOL
  253. RAW_CONNECTION::IsDisableNotificationNeeded(
  254. DWORD dwFilter,
  255. DWORD dwNotification
  256. )
  257. /*++
  258. Routine Description:
  259. If a notification was disabled on the fly, then this routine goes thru
  260. the notification copy path to find whether the given notification is
  261. indeed enabled
  262. Arguments:
  263. dwFilter - Filter number
  264. dwNotification - Notification to check for
  265. Return Value:
  266. BOOL (TRUE is the notification is needed)
  267. --*/
  268. {
  269. W3_FILTER_CONTEXT * pFilterContext;
  270. //
  271. // The only way we could be here is if we determined notifications were
  272. // disabled. That can only happen if we found a W3_CONNECTION associated
  273. //
  274. DBG_ASSERT( _pMainContext != NULL );
  275. pFilterContext = _pMainContext->QueryFilterContext();
  276. DBG_ASSERT( pFilterContext != NULL );
  277. return pFilterContext->IsDisableNotificationNeeded( dwFilter,
  278. dwNotification );
  279. }
  280. PVOID
  281. RAW_CONNECTION::QueryClientContext(
  282. DWORD dwFilter
  283. )
  284. /*++
  285. Routine Description:
  286. Retrieve the filter client context for the given filter
  287. Arguments:
  288. dwFilter - Filter number
  289. Return Value:
  290. Context pointer
  291. --*/
  292. {
  293. //
  294. // If we have a main context associated, then use its merged context
  295. // list
  296. //
  297. if ( _pMainContext == NULL )
  298. {
  299. return _rgContexts[ dwFilter ];
  300. }
  301. else
  302. {
  303. return _pMainContext->QueryFilterContext()->QueryClientContext( dwFilter );
  304. }
  305. }
  306. VOID
  307. RAW_CONNECTION::SetClientContext(
  308. DWORD dwFilter,
  309. PVOID pvContext
  310. )
  311. /*++
  312. Routine Description:
  313. Set client context for the given filter
  314. Arguments:
  315. dwFilter - Filter number
  316. pvContext - Client context
  317. Return Value:
  318. None
  319. --*/
  320. {
  321. //
  322. // If we have a main context, use its merged context list
  323. //
  324. if ( _pMainContext == NULL )
  325. {
  326. _rgContexts[ dwFilter ] = pvContext;
  327. }
  328. else
  329. {
  330. _pMainContext->QueryFilterContext()->SetClientContext( dwFilter,
  331. pvContext );
  332. }
  333. }
  334. HRESULT
  335. RAW_CONNECTION::GetLimitedServerVariables(
  336. LPSTR pszVariableName,
  337. PVOID pvBuffer,
  338. PDWORD pdwSize
  339. )
  340. /*++
  341. Routine Description:
  342. Get the server variables which are possible given that we haven't parsed
  343. the HTTP request yet
  344. Arguments:
  345. pszVariableName - Variable name
  346. pvBuffer - Buffer to receive variable data
  347. pdwSize - On input size of buffer, on output the size needed
  348. Return Value:
  349. HRESULT
  350. --*/
  351. {
  352. STACK_STRA( strVariable, 256 );
  353. HRESULT hr = NO_ERROR;
  354. CHAR achNumber[ 64 ];
  355. if ( strcmp( pszVariableName, "SERVER_PORT" ) == 0 ||
  356. strcmp( pszVariableName, "REMOTE_PORT" ) == 0 )
  357. {
  358. _itoa( pszVariableName[ 0 ] == 'S' ?
  359. _LocalPort : _RemotePort,
  360. achNumber,
  361. 10 );
  362. hr = strVariable.Copy( achNumber );
  363. }
  364. else if ( strcmp( pszVariableName, "REMOTE_ADDR" ) == 0 ||
  365. strcmp( pszVariableName, "LOCAL_ADDR" ) == 0 )
  366. {
  367. DWORD dwAddr;
  368. CHAR szAddr[16];
  369. in_addr inAddr;
  370. dwAddr = pszVariableName[ 0 ] == 'L' ?_LocalAddress : _RemoteAddress;
  371. //
  372. // The dwAddr is reverse order from in_addr...
  373. //
  374. inAddr.S_un.S_un_b.s_b1 = (u_char)(( dwAddr & 0xff000000 ) >> 24);
  375. inAddr.S_un.S_un_b.s_b2 = (u_char)(( dwAddr & 0x00ff0000 ) >> 16);
  376. inAddr.S_un.S_un_b.s_b3 = (u_char)(( dwAddr & 0x0000ff00 ) >> 8);
  377. inAddr.S_un.S_un_b.s_b4 = (u_char) ( dwAddr & 0x000000ff );
  378. LPSTR pszAddr = inet_ntoa( inAddr );
  379. if ( pszAddr == NULL )
  380. {
  381. return HRESULT_FROM_WIN32( GetLastError() );
  382. }
  383. hr = strVariable.Copy( pszAddr );
  384. }
  385. else
  386. {
  387. hr = strVariable.Copy( "" );
  388. }
  389. return strVariable.CopyToBuffer( (LPSTR) pvBuffer, pdwSize );
  390. }
  391. //static
  392. BOOL
  393. WINAPI
  394. RAW_CONNECTION::RawFilterServerSupportFunction(
  395. HTTP_FILTER_CONTEXT * pfc,
  396. enum SF_REQ_TYPE SupportFunction,
  397. void * pData,
  398. ULONG_PTR ul,
  399. ULONG_PTR ul2
  400. )
  401. /*++
  402. Routine Description:
  403. Stream filter SSF crap
  404. Arguments:
  405. pfc - Used to get back the W3_FILTER_CONTEXT and W3_MAIN_CONTEXT pointers
  406. SupportFunction - SSF to invoke (see ISAPI docs)
  407. pData, ul, ul2 - Function specific data
  408. Return Value:
  409. BOOL (use GetLastError() for error)
  410. --*/
  411. {
  412. RAW_CONNECTION * pRawConnection;
  413. HRESULT hr = NO_ERROR;
  414. BOOL fRet;
  415. //
  416. // Primitive parameter validation
  417. //
  418. if ( pfc == NULL ||
  419. pfc->ServerContext == NULL )
  420. {
  421. SetLastError( ERROR_INVALID_PARAMETER );
  422. return FALSE;
  423. }
  424. pRawConnection = (RAW_CONNECTION*) pfc->ServerContext;
  425. DBG_ASSERT( pRawConnection->CheckSignature() );
  426. switch ( SupportFunction )
  427. {
  428. case SF_REQ_SEND_RESPONSE_HEADER:
  429. hr = pRawConnection->SendResponseHeader( (CHAR*) pData,
  430. (CHAR*) ul,
  431. pfc );
  432. break;
  433. case SF_REQ_ADD_HEADERS_ON_DENIAL:
  434. hr = pRawConnection->AddDenialHeaders( (CHAR*) pData );
  435. break;
  436. case SF_REQ_SET_NEXT_READ_SIZE:
  437. pRawConnection->SetNextReadSize( (DWORD) ul );
  438. break;
  439. default:
  440. DBG_ASSERT( FALSE );
  441. hr = HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
  442. }
  443. if ( FAILED( hr ) )
  444. {
  445. SetLastError( WIN32_FROM_HRESULT( hr ) );
  446. return FALSE;
  447. }
  448. return TRUE;
  449. }
  450. //static
  451. BOOL
  452. WINAPI
  453. RAW_CONNECTION::RawFilterGetServerVariable(
  454. HTTP_FILTER_CONTEXT * pfc,
  455. LPSTR lpszVariableName,
  456. LPVOID lpvBuffer,
  457. LPDWORD lpdwSize
  458. )
  459. /*++
  460. Routine Description:
  461. Stream filter GetServerVariable() implementation
  462. Arguments:
  463. pfc - Filter context
  464. lpszVariableName - Variable name
  465. lpvBuffer - Buffer to receive the server variable
  466. lpdwSize - On input, the size of the buffer, on output, the sized needed
  467. Return Value:
  468. BOOL (use GetLastError() for error).
  469. ERROR_INSUFFICIENT_BUFFER if larger buffer needed
  470. ERROR_INVALID_INDEX if the server variable name requested is invalid
  471. --*/
  472. {
  473. HRESULT hr = NO_ERROR;
  474. RAW_CONNECTION * pRawConnection = NULL;
  475. W3_MAIN_CONTEXT * pMainContext;
  476. //
  477. // Primitive parameter validation
  478. //
  479. if ( pfc == NULL ||
  480. pfc->ServerContext == NULL ||
  481. lpdwSize == NULL )
  482. {
  483. SetLastError( ERROR_INVALID_PARAMETER );
  484. return FALSE;
  485. }
  486. pRawConnection = (RAW_CONNECTION*) pfc->ServerContext;
  487. DBG_ASSERT( pRawConnection->CheckSignature() );
  488. //
  489. // If we have a W3_CONNECTION associated, then use its context to
  490. // get at server variables. Otherwise we can only serve the ones that
  491. // make sense
  492. //
  493. pMainContext = pRawConnection->QueryMainContext();
  494. if ( pMainContext != NULL )
  495. {
  496. hr = SERVER_VARIABLE_HASH::GetServerVariable( pMainContext,
  497. lpszVariableName,
  498. (CHAR*) lpvBuffer,
  499. lpdwSize );
  500. }
  501. else
  502. {
  503. //
  504. // We can supply only a few (since we haven't parsed the request yet)
  505. //
  506. hr = pRawConnection->GetLimitedServerVariables( lpszVariableName,
  507. lpvBuffer,
  508. lpdwSize );
  509. }
  510. if ( FAILED( hr ) )
  511. {
  512. SetLastError( WIN32_FROM_HRESULT( hr ) );
  513. return FALSE;
  514. }
  515. return TRUE;
  516. }
  517. //static
  518. BOOL
  519. WINAPI
  520. RAW_CONNECTION::RawFilterWriteClient(
  521. HTTP_FILTER_CONTEXT * pfc,
  522. LPVOID Buffer,
  523. LPDWORD lpdwBytes,
  524. DWORD dwReserved
  525. )
  526. /*++
  527. Routine Description:
  528. Synchronous WriteClient() for stream filter
  529. Arguments:
  530. pfc - Filter context
  531. Buffer - buffer to write to client
  532. lpdwBytes - On input, the size of the input buffer. On output, the number
  533. of bytes sent
  534. dwReserved - Reserved
  535. Return Value:
  536. BOOL (use GetLastError() for error).
  537. --*/
  538. {
  539. HRESULT hr;
  540. RAW_CONNECTION * pRawConnection = NULL;
  541. PVOID pvContext;
  542. RAW_STREAM_INFO rawStreamInfo;
  543. BOOL fComplete = FALSE;
  544. //
  545. // Primitive parameter validation
  546. //
  547. if ( pfc == NULL ||
  548. pfc->ServerContext == NULL ||
  549. Buffer == NULL )
  550. {
  551. SetLastError( ERROR_INVALID_PARAMETER );
  552. return FALSE;
  553. }
  554. pRawConnection = (RAW_CONNECTION*) pfc->ServerContext;
  555. DBG_ASSERT( pRawConnection->CheckSignature() );
  556. //
  557. // Remember the filter context since calling filters will overwrite it
  558. //
  559. pvContext = pfc->pFilterContext;
  560. //
  561. // We need to notify all write raw data filters which are a higher
  562. // priority than the current filter
  563. //
  564. if ( pRawConnection->_dwCurrentFilter > 0 )
  565. {
  566. rawStreamInfo.pbBuffer = (BYTE*) Buffer;
  567. rawStreamInfo.cbBuffer = *lpdwBytes;
  568. rawStreamInfo.cbData = rawStreamInfo.cbBuffer;
  569. hr = pRawConnection->NotifyRawWriteFilters( &rawStreamInfo,
  570. &fComplete,
  571. pRawConnection->_dwCurrentFilter - 1 );
  572. if ( FAILED( hr ) )
  573. {
  574. goto Finished;
  575. }
  576. }
  577. pfc->pFilterContext = pvContext;
  578. //
  579. // Now call back into the stream filter to send the data. In transmit
  580. // SSL might do its thing with the data as well
  581. //
  582. hr = pRawConnection->_pfnSendDataBack( pRawConnection->_pvStreamContext,
  583. &rawStreamInfo );
  584. if ( FAILED( hr ) )
  585. {
  586. goto Finished;
  587. }
  588. return TRUE;
  589. Finished:
  590. if ( FAILED( hr ) )
  591. {
  592. SetLastError( WIN32_FROM_HRESULT( hr ) );
  593. return FALSE;
  594. }
  595. return TRUE;
  596. }
  597. //static
  598. VOID *
  599. WINAPI
  600. RAW_CONNECTION::RawFilterAllocateMemory(
  601. HTTP_FILTER_CONTEXT * pfc,
  602. DWORD cbSize,
  603. DWORD dwReserved
  604. )
  605. /*++
  606. Routine Description:
  607. Used by filters to allocate memory freed on connection close
  608. Arguments:
  609. pfc - Filter context
  610. cbSize - Amount to allocate
  611. dwReserved - Reserved
  612. Return Value:
  613. A pointer to the allocated memory
  614. --*/
  615. {
  616. RAW_CONNECTION * pRawConnection = NULL;
  617. //
  618. // Primitive parameter validation
  619. //
  620. if ( pfc == NULL ||
  621. pfc->ServerContext == NULL )
  622. {
  623. SetLastError( ERROR_INVALID_PARAMETER );
  624. return NULL;
  625. }
  626. pRawConnection = (RAW_CONNECTION*) pfc->ServerContext;
  627. DBG_ASSERT( pRawConnection->CheckSignature() );
  628. return pRawConnection->AllocateFilterMemory( cbSize );
  629. }
  630. //static
  631. BOOL
  632. WINAPI
  633. RAW_CONNECTION::RawFilterAddResponseHeaders(
  634. HTTP_FILTER_CONTEXT * pfc,
  635. LPSTR lpszHeaders,
  636. DWORD dwReserved
  637. )
  638. /*++
  639. Routine Description:
  640. Add response headers to whatever response eventually gets sent
  641. Arguments:
  642. pfc - Filter context
  643. lpszHeaders - Headers to send (\r\n delimited)
  644. dwReserved - Reserved
  645. Return Value:
  646. BOOL (use GetLastError() for error).
  647. --*/
  648. {
  649. HRESULT hr;
  650. RAW_CONNECTION * pRawConnection;
  651. W3_MAIN_CONTEXT * pMainContext = NULL;
  652. W3_FILTER_CONTEXT * pFilterContext;
  653. //
  654. // Primitive parameter validation
  655. //
  656. if ( pfc == NULL ||
  657. pfc->ServerContext == NULL ||
  658. lpszHeaders == NULL )
  659. {
  660. SetLastError( ERROR_INVALID_PARAMETER );
  661. return FALSE;
  662. }
  663. pRawConnection = (RAW_CONNECTION*) pfc->ServerContext;
  664. DBG_ASSERT( pRawConnection->CheckSignature() );
  665. pMainContext = pRawConnection->QueryMainContext();
  666. if ( pMainContext != NULL )
  667. {
  668. pFilterContext = pMainContext->QueryFilterContext();
  669. DBG_ASSERT( pFilterContext != NULL );
  670. hr = pFilterContext->AddResponseHeaders( lpszHeaders );
  671. }
  672. else
  673. {
  674. hr = pRawConnection->AddResponseHeaders( lpszHeaders );
  675. }
  676. if ( FAILED( hr ) )
  677. {
  678. SetLastError( WIN32_FROM_HRESULT( hr ) );
  679. return FALSE;
  680. }
  681. return TRUE;
  682. }
  683. //static
  684. HRESULT
  685. RAW_CONNECTION::ProcessNewConnection(
  686. CONNECTION_INFO * pConnectionInfo,
  687. PVOID * ppConnectionState
  688. )
  689. /*++
  690. Routine Description:
  691. Called for every new raw connection to server
  692. Arguments:
  693. pConnectionInfo - Information about the local/remote addresses
  694. ppConnectionState - Connection state to be associated with raw connection
  695. Return Value:
  696. HRESULT
  697. --*/
  698. {
  699. RAW_CONNECTION * pConnection = NULL;
  700. LK_RETCODE lkrc;
  701. if ( pConnectionInfo == NULL ||
  702. ppConnectionState == NULL )
  703. {
  704. DBG_ASSERT( FALSE );
  705. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  706. }
  707. *ppConnectionState = NULL;
  708. //
  709. // Try to create and add the connection
  710. //
  711. pConnection = new RAW_CONNECTION( pConnectionInfo );
  712. if ( pConnection == NULL )
  713. {
  714. return HRESULT_FROM_WIN32( GetLastError() );
  715. }
  716. lkrc = sm_pRawConnectionHash->InsertRecord( pConnection );
  717. if ( lkrc != LK_SUCCESS )
  718. {
  719. pConnection->DereferenceRawConnection();
  720. pConnection = NULL;
  721. return HRESULT_FROM_WIN32( lkrc );
  722. }
  723. *ppConnectionState = pConnection;
  724. return NO_ERROR;
  725. }
  726. //static
  727. HRESULT
  728. RAW_CONNECTION::ProcessRawRead(
  729. RAW_STREAM_INFO * pRawStreamInfo,
  730. PVOID pContext,
  731. BOOL * pfReadMore,
  732. BOOL * pfComplete,
  733. DWORD * pcbNextReadSize
  734. )
  735. /*++
  736. Routine Description:
  737. Notify ISAPI read raw data filters
  738. Arguments:
  739. pRawStreamInfo - The raw stream to muck with
  740. pContext - Raw connection context
  741. pfReadMore - Set to TRUE if we need to read more data
  742. pfComplete - Set to TRUE if we want to disconnect client
  743. pcbNextReadSize - Set to next read size (0 means use default size)
  744. Return Value:
  745. HRESULT
  746. --*/
  747. {
  748. RAW_CONNECTION * pConnection = NULL;
  749. HRESULT hr = NO_ERROR;
  750. W3_MAIN_CONTEXT * pMainContext;
  751. if ( pRawStreamInfo == NULL ||
  752. pfReadMore == NULL ||
  753. pfComplete == NULL ||
  754. pContext == NULL ||
  755. pcbNextReadSize == NULL )
  756. {
  757. DBG_ASSERT( FALSE );
  758. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  759. }
  760. *pfReadMore = FALSE;
  761. *pfComplete = FALSE;
  762. pConnection = (RAW_CONNECTION*) pContext;
  763. DBG_ASSERT( pConnection->CheckSignature() );
  764. pConnection->SetNextReadSize( 0 );
  765. //
  766. // Synchronize access to the filter to prevent raw notifications from
  767. // occurring at the same time as regular worker process notifications
  768. //
  769. pMainContext = pConnection->QueryMainContext();
  770. if ( pMainContext != NULL )
  771. {
  772. pMainContext->QueryFilterContext()->FilterLock();
  773. }
  774. hr = pConnection->NotifyRawReadFilters( pRawStreamInfo,
  775. pfReadMore,
  776. pfComplete );
  777. if ( pMainContext != NULL )
  778. {
  779. pMainContext->QueryFilterContext()->FilterUnlock();
  780. }
  781. *pcbNextReadSize = pConnection->QueryNextReadSize();
  782. return hr;
  783. }
  784. HRESULT
  785. RAW_CONNECTION::NotifyRawReadFilters(
  786. RAW_STREAM_INFO * pRawStreamInfo,
  787. BOOL * pfReadMore,
  788. BOOL * pfComplete
  789. )
  790. /*++
  791. Routine Description:
  792. Notify raw read filters
  793. Arguments:
  794. pRawStreamInfo - Raw stream info
  795. pfReadMore - Set to TRUE to we should read more data
  796. pfComplete - Set to TRUE if we should disconnect
  797. Return Value:
  798. HRESULT
  799. --*/
  800. {
  801. HTTP_FILTER_DLL * pFilterDll;
  802. DWORD err;
  803. SF_STATUS_TYPE sfStatus;
  804. DWORD i;
  805. PVOID pvtmp;
  806. PVOID pvCurrentClientContext;
  807. FILTER_LIST * pFilterList;
  808. HTTP_FILTER_RAW_DATA hfrd;
  809. if ( pRawStreamInfo == NULL ||
  810. pfReadMore == NULL ||
  811. pfComplete == NULL )
  812. {
  813. DBG_ASSERT( FALSE );
  814. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  815. }
  816. *pfComplete = FALSE;
  817. *pfReadMore = FALSE;
  818. //
  819. // Setup filter raw object
  820. //
  821. hfrd.pvInData = pRawStreamInfo->pbBuffer;
  822. hfrd.cbInData = pRawStreamInfo->cbData;
  823. hfrd.cbInBuffer = pRawStreamInfo->cbBuffer;
  824. //
  825. // In certain cases, we can send a notification to a filter while we're still
  826. // processing another filter's notification. In that case, we need to make sure
  827. // we restore the current filter's context when we're done with the notifications
  828. //
  829. pvCurrentClientContext = _hfc.pFilterContext;
  830. pFilterList = QueryFilterList();
  831. DBG_ASSERT( pFilterList != NULL );
  832. for ( i = 0; i < pFilterList->QueryFilterCount(); i++ )
  833. {
  834. pFilterDll = pFilterList->QueryDll( i );
  835. //
  836. // Notification flags are cached in the HTTP_FILTER object, but they're
  837. // only copied from the actual HTTP_FILTER_DLL object if a filter dll
  838. // disables a particular notification [sort of a copy-on-write scheme].
  839. // If a filter dll disables/changes a notification, we need to check the flags
  840. // in the HTTP_FILTER object, not those in the HTTP_FILTER_DLL object
  841. //
  842. if ( !QueryNotificationChanged() )
  843. {
  844. if ( !pFilterDll->IsNotificationNeeded( SF_NOTIFY_READ_RAW_DATA,
  845. _hfc.fIsSecurePort ) )
  846. {
  847. continue;
  848. }
  849. }
  850. else
  851. {
  852. if ( !IsDisableNotificationNeeded( i,
  853. SF_NOTIFY_READ_RAW_DATA ) )
  854. {
  855. continue;
  856. }
  857. }
  858. _hfc.pFilterContext = QueryClientContext( i );
  859. pvtmp = _hfc.pFilterContext;
  860. //
  861. // Keep track of the current filter so that we know which filters
  862. // to notify when a raw filter does a write client
  863. //
  864. _dwCurrentFilter = i;
  865. sfStatus = (SF_STATUS_TYPE)
  866. pFilterDll->QueryEntryPoint()( &_hfc,
  867. SF_NOTIFY_READ_RAW_DATA,
  868. &hfrd );
  869. if ( pvtmp != _hfc.pFilterContext )
  870. {
  871. SetClientContext( i, _hfc.pFilterContext );
  872. pFilterDll->SetHasSetContextBefore();
  873. }
  874. switch ( sfStatus )
  875. {
  876. default:
  877. DBGPRINTF(( DBG_CONTEXT,
  878. "Unknown status code from filter %d\n",
  879. sfStatus ));
  880. //
  881. // Fall through
  882. //
  883. case SF_STATUS_REQ_NEXT_NOTIFICATION:
  884. continue;
  885. case SF_STATUS_REQ_ERROR:
  886. _hfc.pFilterContext = pvCurrentClientContext;
  887. return E_FAIL;
  888. case SF_STATUS_REQ_FINISHED:
  889. case SF_STATUS_REQ_FINISHED_KEEP_CONN: // Not supported at this point
  890. *pfComplete = TRUE;
  891. goto Exit;
  892. case SF_STATUS_REQ_READ_NEXT:
  893. *pfReadMore = TRUE;
  894. goto Exit;
  895. case SF_STATUS_REQ_HANDLED_NOTIFICATION:
  896. //
  897. // Don't notify any other filters
  898. //
  899. goto Exit;
  900. }
  901. }
  902. Exit:
  903. pRawStreamInfo->pbBuffer = (BYTE*) hfrd.pvInData;
  904. pRawStreamInfo->cbData = hfrd.cbInData;
  905. pRawStreamInfo->cbBuffer = hfrd.cbInBuffer;
  906. //
  907. // Reset the filter context we came in with
  908. //
  909. _hfc.pFilterContext = pvCurrentClientContext;
  910. return NO_ERROR;
  911. }
  912. //static
  913. HRESULT
  914. RAW_CONNECTION::ProcessRawWrite(
  915. RAW_STREAM_INFO * pRawStreamInfo,
  916. PVOID pvContext,
  917. BOOL * pfComplete
  918. )
  919. /*++
  920. Routine Description:
  921. Entry point called by stream filter to handle data coming from the
  922. application. We will call SF_NOTIFY_SEND_RAW_DATA filter notifications
  923. here
  924. Arguments:
  925. pRawStreamInfo - The stream to process, as well as an optional opaque
  926. context set by the RAW_CONNECTION code
  927. pvContext - Context pass back
  928. pfComplete - Set to TRUE if we should disconnect
  929. Return Value:
  930. HRESULT
  931. --*/
  932. {
  933. RAW_CONNECTION * pConnection = NULL;
  934. W3_MAIN_CONTEXT * pMainContext;
  935. HRESULT hr = NO_ERROR;
  936. DWORD cbAppRead;
  937. if ( pRawStreamInfo == NULL ||
  938. pfComplete == NULL )
  939. {
  940. DBG_ASSERT( FALSE );
  941. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  942. }
  943. *pfComplete = FALSE;
  944. return NO_ERROR;
  945. }
  946. HRESULT
  947. RAW_CONNECTION::NotifyRawWriteFilters(
  948. RAW_STREAM_INFO * pRawStreamInfo,
  949. BOOL * pfComplete,
  950. DWORD dwStartFilter
  951. )
  952. /*++
  953. Routine Description:
  954. Notify raw write filters
  955. Arguments:
  956. pRawStreamInfo - Raw stream to munge
  957. pfComplete - Set to TRUE if we should disconnect now
  958. dwStartFilter - Filter to start notifying. If this valid is INVALID_DLL,
  959. then simply start with the lowest priority filter
  960. Return Value:
  961. HRESULT
  962. --*/
  963. {
  964. HTTP_FILTER_DLL * pFilterDll;
  965. DWORD err;
  966. SF_STATUS_TYPE sfStatus;
  967. DWORD i;
  968. PVOID pvtmp;
  969. PVOID pvCurrentClientContext;
  970. FILTER_LIST * pFilterList;
  971. HTTP_FILTER_RAW_DATA hfrd;
  972. if ( pRawStreamInfo == NULL ||
  973. pfComplete == NULL )
  974. {
  975. DBG_ASSERT( FALSE );
  976. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  977. }
  978. *pfComplete = FALSE;
  979. hfrd.pvInData = pRawStreamInfo->pbBuffer;
  980. hfrd.cbInData = pRawStreamInfo->cbData;
  981. hfrd.cbInBuffer = pRawStreamInfo->cbBuffer;
  982. //
  983. // In certain cases, we can send a notification to a filter while we're still
  984. // processing another filter's notification. In that case, we need to make sure
  985. // we restore the current filter's context when we're done with the notifications
  986. //
  987. pvCurrentClientContext = _hfc.pFilterContext;
  988. pFilterList = QueryFilterList();
  989. DBG_ASSERT( pFilterList != NULL );
  990. if ( dwStartFilter == INVALID_DLL )
  991. {
  992. dwStartFilter = pFilterList->QueryFilterCount() - 1;
  993. }
  994. i = dwStartFilter;
  995. do
  996. {
  997. pFilterDll = pFilterList->QueryDll( i );
  998. //
  999. // Notification flags are cached in the HTTP_FILTER object, but they're
  1000. // only copied from the actual HTTP_FILTER_DLL object if a filter dll
  1001. // disables a particular notification [sort of a copy-on-write scheme].
  1002. // If a filter dll disables/changes a notification, we need to check the flags
  1003. // in the HTTP_FILTER object, not those in the HTTP_FILTER_DLL object
  1004. //
  1005. if ( !QueryNotificationChanged() )
  1006. {
  1007. if ( !pFilterDll->IsNotificationNeeded( SF_NOTIFY_SEND_RAW_DATA,
  1008. _hfc.fIsSecurePort ) )
  1009. {
  1010. continue;
  1011. }
  1012. }
  1013. else
  1014. {
  1015. if ( !IsDisableNotificationNeeded( i,
  1016. SF_NOTIFY_SEND_RAW_DATA ) )
  1017. {
  1018. continue;
  1019. }
  1020. }
  1021. //
  1022. // Another slimy optimization. If this filter has never associated
  1023. // context with connection, then we don't have to do the lookup
  1024. //
  1025. _hfc.pFilterContext = QueryClientContext( i );
  1026. pvtmp = _hfc.pFilterContext;
  1027. //
  1028. // Keep track of the current filter so that we know which filters
  1029. // to notify when a raw filter does a write client
  1030. //
  1031. _dwCurrentFilter = i;
  1032. sfStatus = (SF_STATUS_TYPE)
  1033. pFilterDll->QueryEntryPoint()( &_hfc,
  1034. SF_NOTIFY_SEND_RAW_DATA,
  1035. &hfrd );
  1036. if ( pvtmp != _hfc.pFilterContext )
  1037. {
  1038. SetClientContext( i, _hfc.pFilterContext );
  1039. pFilterDll->SetHasSetContextBefore();
  1040. }
  1041. switch ( sfStatus )
  1042. {
  1043. default:
  1044. DBGPRINTF(( DBG_CONTEXT,
  1045. "Unknown status code from filter %d\n",
  1046. sfStatus ));
  1047. //
  1048. // Fall through
  1049. //
  1050. case SF_STATUS_REQ_NEXT_NOTIFICATION:
  1051. continue;
  1052. case SF_STATUS_REQ_ERROR:
  1053. _hfc.pFilterContext = pvCurrentClientContext;
  1054. return E_FAIL;
  1055. case SF_STATUS_REQ_FINISHED:
  1056. case SF_STATUS_REQ_FINISHED_KEEP_CONN: // Not supported at this point
  1057. *pfComplete = TRUE;
  1058. goto Exit;
  1059. case SF_STATUS_REQ_HANDLED_NOTIFICATION:
  1060. //
  1061. // Don't notify any other filters
  1062. //
  1063. goto Exit;
  1064. }
  1065. }
  1066. while ( i-- > 0 );
  1067. Exit:
  1068. pRawStreamInfo->pbBuffer = (BYTE*) hfrd.pvInData;
  1069. pRawStreamInfo->cbData = hfrd.cbInData;
  1070. pRawStreamInfo->cbBuffer = hfrd.cbInBuffer;
  1071. //
  1072. // Reset the filter context we came in with
  1073. //
  1074. _hfc.pFilterContext = pvCurrentClientContext;
  1075. return NO_ERROR;
  1076. }
  1077. HRESULT
  1078. RAW_CONNECTION::NotifyEndOfNetSessionFilters(
  1079. VOID
  1080. )
  1081. /*++
  1082. Routine Description:
  1083. Notify END_OF_NET_SESSION filters
  1084. Arguments:
  1085. None
  1086. Return Value:
  1087. HRESULT
  1088. --*/
  1089. {
  1090. HTTP_FILTER_DLL * pFilterDll;
  1091. DWORD err;
  1092. SF_STATUS_TYPE sfStatus;
  1093. DWORD i;
  1094. PVOID pvtmp;
  1095. PVOID pvCurrentClientContext;
  1096. FILTER_LIST * pFilterList;
  1097. HTTP_FILTER_RAW_DATA hfrd;
  1098. //
  1099. // In certain cases, we can send a notification to a filter while we're still
  1100. // processing another filter's notification. In that case, we need to make sure
  1101. // we restore the current filter's context when we're done with the notifications
  1102. //
  1103. pvCurrentClientContext = _hfc.pFilterContext;
  1104. pFilterList = QueryFilterList();
  1105. DBG_ASSERT( pFilterList != NULL );
  1106. for ( i = 0; i < pFilterList->QueryFilterCount(); i++ )
  1107. {
  1108. pFilterDll = pFilterList->QueryDll( i );
  1109. if ( !QueryNotificationChanged() )
  1110. {
  1111. if ( !pFilterDll->IsNotificationNeeded( SF_NOTIFY_END_OF_NET_SESSION,
  1112. _hfc.fIsSecurePort ) )
  1113. {
  1114. continue;
  1115. }
  1116. }
  1117. else
  1118. {
  1119. if ( !IsDisableNotificationNeeded( i,
  1120. SF_NOTIFY_END_OF_NET_SESSION ) )
  1121. {
  1122. continue;
  1123. }
  1124. }
  1125. _hfc.pFilterContext = QueryClientContext( i );
  1126. pvtmp = _hfc.pFilterContext;
  1127. //
  1128. // Keep track of the current filter so that we know which filters
  1129. // to notify when a raw filter does a write client
  1130. //
  1131. _dwCurrentFilter = i;
  1132. sfStatus = (SF_STATUS_TYPE)
  1133. pFilterDll->QueryEntryPoint()( &_hfc,
  1134. SF_NOTIFY_END_OF_NET_SESSION,
  1135. &hfrd );
  1136. if ( pvtmp != _hfc.pFilterContext )
  1137. {
  1138. SetClientContext( i, _hfc.pFilterContext );
  1139. pFilterDll->SetHasSetContextBefore();
  1140. }
  1141. switch ( sfStatus )
  1142. {
  1143. default:
  1144. DBGPRINTF(( DBG_CONTEXT,
  1145. "Unknown status code from filter %d\n",
  1146. sfStatus ));
  1147. //
  1148. // Fall through
  1149. //
  1150. case SF_STATUS_REQ_NEXT_NOTIFICATION:
  1151. continue;
  1152. case SF_STATUS_REQ_ERROR:
  1153. _hfc.pFilterContext = pvCurrentClientContext;
  1154. return E_FAIL;
  1155. case SF_STATUS_REQ_FINISHED:
  1156. case SF_STATUS_REQ_FINISHED_KEEP_CONN: // Not supported at this point
  1157. goto Exit;
  1158. case SF_STATUS_REQ_HANDLED_NOTIFICATION:
  1159. //
  1160. // Don't notify any other filters
  1161. //
  1162. goto Exit;
  1163. }
  1164. }
  1165. Exit:
  1166. //
  1167. // Reset the filter context we came in with
  1168. //
  1169. _hfc.pFilterContext = pvCurrentClientContext;
  1170. return NO_ERROR;
  1171. }
  1172. //static
  1173. VOID
  1174. RAW_CONNECTION::ProcessConnectionClose(
  1175. PVOID pvContext
  1176. )
  1177. /*++
  1178. Routine Description:
  1179. Entry point called by stream filter when a connection has closed
  1180. Arguments:
  1181. pvContext - Opaque context associated with the connection
  1182. Return Value:
  1183. None
  1184. --*/
  1185. {
  1186. RAW_CONNECTION * pRawConnection;
  1187. pRawConnection = (RAW_CONNECTION*) pvContext;
  1188. if ( pRawConnection != NULL )
  1189. {
  1190. DBG_ASSERT( pRawConnection->CheckSignature() );
  1191. //
  1192. // We're done with the raw connection. Delete it from hash table
  1193. // In the process, this will dereference the connection
  1194. //
  1195. DBG_ASSERT( sm_pRawConnectionHash != NULL );
  1196. sm_pRawConnectionHash->DeleteRecord( pRawConnection );
  1197. }
  1198. }
  1199. VOID
  1200. RAW_CONNECTION::CopyAllocatedFilterMemory(
  1201. W3_FILTER_CONTEXT * pFilterContext
  1202. )
  1203. /*++
  1204. Routine Description:
  1205. Copy over any allocated filter memory items
  1206. Arguments:
  1207. pFilterContext - Destination of filter memory item references
  1208. Return Value:
  1209. None
  1210. --*/
  1211. {
  1212. FILTER_POOL_ITEM * pfpi;
  1213. //
  1214. // We need to grab the raw connection lock since we don't want a
  1215. // read-raw data notification to muck with the pool list while we
  1216. // are copying it over to the W3_CONNECTION
  1217. //
  1218. pFilterContext->FilterLock();
  1219. while ( !IsListEmpty( &_PoolHead ) )
  1220. {
  1221. pfpi = CONTAINING_RECORD( _PoolHead.Flink,
  1222. FILTER_POOL_ITEM,
  1223. _ListEntry );
  1224. RemoveEntryList( &pfpi->_ListEntry );
  1225. InitializeListHead( &pfpi->_ListEntry );
  1226. //
  1227. // Copy the pool item to the other list
  1228. //
  1229. pFilterContext->AddFilterPoolItem( pfpi );
  1230. }
  1231. pFilterContext->FilterUnlock();
  1232. }
  1233. VOID
  1234. RAW_CONNECTION::CopyContextPointers(
  1235. W3_FILTER_CONTEXT * pFilterContext
  1236. )
  1237. /*++
  1238. Routine Description:
  1239. The global filter list is constant, in addition, when an instance filter
  1240. list is built, the global filters are always built into the list. After
  1241. the instance filter list has been identified, we need to copy any non-null
  1242. client filter context values from the global filter list to the new
  1243. positions in the instance filter list. For example:
  1244. Global List & | Instance List &
  1245. context values | new context value positions
  1246. |
  1247. G1 0 | I1 0
  1248. G2 555 | G1 0
  1249. G3 123 | G2 555
  1250. | I2 0
  1251. | G3 123
  1252. Note: This scheme precludes having the same .dll be used for both a
  1253. global and per-instance dll. Since global filters are automatically
  1254. per-instance this shouldn't be an interesting case.
  1255. --*/
  1256. {
  1257. DWORD i, j;
  1258. DWORD cGlobal;
  1259. DWORD cInstance;
  1260. HTTP_FILTER_DLL * pFilterDll;
  1261. FILTER_LIST * pGlobalFilterList;
  1262. FILTER_LIST * pInstanceFilterList;
  1263. pFilterContext->FilterLock();
  1264. DBG_ASSERT( pFilterContext != NULL );
  1265. pGlobalFilterList = FILTER_LIST::QueryGlobalList();
  1266. DBG_ASSERT( pGlobalFilterList != NULL );
  1267. cGlobal = pGlobalFilterList->QueryFilterCount();
  1268. pInstanceFilterList = pFilterContext->QueryFilterList();
  1269. DBG_ASSERT( pInstanceFilterList != NULL );
  1270. cInstance = pInstanceFilterList->QueryFilterCount();
  1271. //
  1272. // If no global filters or no instance filters, then there won't be
  1273. // any filter context pointers that need adjusting
  1274. //
  1275. if ( !cGlobal || !cInstance )
  1276. {
  1277. goto Finished;
  1278. }
  1279. //
  1280. // For each global list context pointer, find the filter in the instance
  1281. // list and adjust
  1282. //
  1283. for ( i = 0; i < cGlobal; i++ )
  1284. {
  1285. if ( _rgContexts[ i ] != NULL )
  1286. {
  1287. pFilterDll = pGlobalFilterList->QueryDll( i );
  1288. //
  1289. // We found one. Find the filter in instance list and set
  1290. //
  1291. for ( j = 0; j < cInstance; j++ )
  1292. {
  1293. if ( pInstanceFilterList->QueryDll( j ) == pFilterDll )
  1294. {
  1295. pFilterContext->SetClientContext( j, _rgContexts[ i ] );
  1296. }
  1297. }
  1298. }
  1299. }
  1300. Finished:
  1301. pFilterContext->FilterUnlock();
  1302. }
  1303. HRESULT
  1304. RAW_CONNECTION::CopyHeaders(
  1305. W3_FILTER_CONTEXT * pFilterContext
  1306. )
  1307. /*++
  1308. Routine Description:
  1309. Copy denied/response headers from read raw
  1310. Arguments:
  1311. pFilterContext - Filter context to copy to
  1312. Return Value:
  1313. HRESULT
  1314. --*/
  1315. {
  1316. HRESULT hr;
  1317. if ( pFilterContext == NULL )
  1318. {
  1319. DBG_ASSERT( FALSE );
  1320. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  1321. }
  1322. hr = pFilterContext->AddDenialHeaders( _strAddDenialHeaders.QueryStr() );
  1323. if ( FAILED( hr ) )
  1324. {
  1325. return hr;
  1326. }
  1327. hr = pFilterContext->AddResponseHeaders( _strAddResponseHeaders.QueryStr() );
  1328. if ( FAILED( hr ) )
  1329. {
  1330. return hr;
  1331. }
  1332. _strAddDenialHeaders.Reset();
  1333. _strAddResponseHeaders.Reset();
  1334. return NO_ERROR;
  1335. }
  1336. HRESULT
  1337. RAW_CONNECTION::SendResponseHeader(
  1338. CHAR * pszStatus,
  1339. CHAR * pszAdditionalHeaders,
  1340. HTTP_FILTER_CONTEXT * pfc
  1341. )
  1342. /*++
  1343. Routine Description:
  1344. Called when raw filters want to send a response header. Depending
  1345. on whether a W3_CONNECTION is associated or not, we will either
  1346. send the stream ourselves here, or call in the main context's
  1347. response facilities
  1348. Arguments:
  1349. pszStatus - ANSI status line
  1350. pszAdditionalHeaders - Any additional headers to send
  1351. pfc - Filter context (to be passed to FilterWriteClient())
  1352. Return Value:
  1353. HRESULT
  1354. --*/
  1355. {
  1356. W3_MAIN_CONTEXT * pMainContext = NULL;
  1357. STACK_STRA( strResponse, 256 );
  1358. HRESULT hr = NO_ERROR;
  1359. DWORD cbBytes = 0;
  1360. BOOL fRet = FALSE;
  1361. W3_RESPONSE * pResponse = NULL;
  1362. if ( pszStatus == NULL &&
  1363. pszAdditionalHeaders == NULL )
  1364. {
  1365. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  1366. }
  1367. //
  1368. // Which response are we touching?
  1369. //
  1370. pMainContext = QueryMainContext();
  1371. if ( pMainContext != NULL )
  1372. {
  1373. pResponse = pMainContext->QueryResponse();
  1374. }
  1375. else
  1376. {
  1377. pResponse = &_response;
  1378. }
  1379. //
  1380. // Build up a response from what ISAPI gave us
  1381. //
  1382. hr = pResponse->BuildResponseFromIsapi( pMainContext,
  1383. pszStatus,
  1384. pszAdditionalHeaders,
  1385. pszAdditionalHeaders ?
  1386. strlen( pszAdditionalHeaders ) : 0 );
  1387. if ( FAILED( hr ) )
  1388. {
  1389. return hr;
  1390. }
  1391. //
  1392. // Now if we have a w3 context then we can send the response normally.
  1393. // Otherwise we must use the UL filter API
  1394. //
  1395. if ( pMainContext != NULL )
  1396. {
  1397. hr = pMainContext->SendResponse( W3_FLAG_SYNC | W3_FLAG_NO_ERROR_BODY );
  1398. }
  1399. else
  1400. {
  1401. //
  1402. // Add denial/response headers
  1403. //
  1404. if ( pResponse->QueryStatusCode() == HttpStatusUnauthorized.statusCode )
  1405. {
  1406. hr = pResponse->AppendResponseHeaders( _strAddDenialHeaders );
  1407. if ( FAILED( hr ) )
  1408. {
  1409. return hr;
  1410. }
  1411. }
  1412. hr = pResponse->AppendResponseHeaders( _strAddResponseHeaders );
  1413. if ( FAILED( hr ) )
  1414. {
  1415. return hr;
  1416. }
  1417. hr = pResponse->GetRawResponseStream( &strResponse );
  1418. if ( FAILED( hr ) )
  1419. {
  1420. return hr;
  1421. }
  1422. //
  1423. // Go thru WriteClient() so the right filtering happens on the
  1424. // response
  1425. //
  1426. cbBytes = strResponse.QueryCB();
  1427. fRet = RAW_CONNECTION::RawFilterWriteClient( pfc,
  1428. strResponse.QueryStr(),
  1429. &cbBytes,
  1430. 0 );
  1431. if ( !fRet )
  1432. {
  1433. hr = HRESULT_FROM_WIN32( GetLastError() );
  1434. }
  1435. }
  1436. return hr;
  1437. }
  1438. //static
  1439. HRESULT
  1440. RAW_CONNECTION::FindConnection(
  1441. HTTP_RAW_CONNECTION_ID rawConnectionId,
  1442. RAW_CONNECTION ** ppRawConnection
  1443. )
  1444. /*++
  1445. Routine Description:
  1446. Find and return raw connection if found
  1447. Arguments:
  1448. rawConnectionId - Raw connection ID from UL_HTTP_REQUEST
  1449. ppRawConnection - Set to raw connection if found
  1450. Return Value:
  1451. HRESULT
  1452. --*/
  1453. {
  1454. LK_RETCODE lkrc;
  1455. if ( ppRawConnection == NULL ||
  1456. rawConnectionId == HTTP_NULL_ID )
  1457. {
  1458. DBG_ASSERT( FALSE );
  1459. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  1460. }
  1461. DBG_ASSERT( sm_pRawConnectionHash != NULL );
  1462. lkrc = sm_pRawConnectionHash->FindKey( rawConnectionId,
  1463. ppRawConnection );
  1464. if ( lkrc != LK_SUCCESS )
  1465. {
  1466. return HRESULT_FROM_WIN32( ERROR_FILE_NOT_FOUND );
  1467. }
  1468. else
  1469. {
  1470. return NO_ERROR;
  1471. }
  1472. }