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.

2452 lines
61 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. PTRACE_LOG RAW_CONNECTION::sm_pTraceLog;
  18. BOOL RAW_CONNECTION::sm_fNotifyRawReadData = FALSE;
  19. RAW_CONNECTION::RAW_CONNECTION(
  20. CONNECTION_INFO * pConnectionInfo
  21. )
  22. {
  23. _cRefs = 1;
  24. _pMainContext = NULL;
  25. _dwCurrentFilter = INVALID_DLL;
  26. DBG_ASSERT( pConnectionInfo != NULL );
  27. _hfc.cbSize = sizeof( _hfc );
  28. _hfc.Revision = HTTP_FILTER_REVISION;
  29. _hfc.ServerContext = (void *) this;
  30. _hfc.ulReserved = 0;
  31. _hfc.fIsSecurePort = pConnectionInfo->fIsSecure;
  32. _hfc.pFilterContext = NULL;
  33. _hfc.ServerSupportFunction = RawFilterServerSupportFunction;
  34. _hfc.GetServerVariable = RawFilterGetServerVariable;
  35. _hfc.AddResponseHeaders = RawFilterAddResponseHeaders;
  36. _hfc.WriteClient = RawFilterWriteClient;
  37. _hfc.AllocMem = RawFilterAllocateMemory;
  38. ZeroMemory( &_rgContexts, sizeof( _rgContexts ) );
  39. InitializeListHead( &_PoolHead );
  40. _pfnSendDataBack = pConnectionInfo->pfnSendDataBack;
  41. _pvStreamContext = pConnectionInfo->pvStreamContext;
  42. _LocalAddressType = pConnectionInfo->LocalAddressType;
  43. _RemoteAddressType = pConnectionInfo->RemoteAddressType;
  44. if( pConnectionInfo->LocalAddressType == AF_INET )
  45. {
  46. memcpy( &_SockLocalAddress,
  47. &pConnectionInfo->SockLocalAddress,
  48. sizeof( SOCKADDR_IN ) );
  49. }
  50. else if( pConnectionInfo->LocalAddressType == AF_INET6 )
  51. {
  52. memcpy( &_SockLocalAddress,
  53. &pConnectionInfo->SockLocalAddress,
  54. sizeof( SOCKADDR_IN6 ) );
  55. }
  56. else
  57. {
  58. DBG_ASSERT( FALSE );
  59. }
  60. if( pConnectionInfo->RemoteAddressType == AF_INET )
  61. {
  62. memcpy( &_SockRemoteAddress,
  63. &pConnectionInfo->SockRemoteAddress,
  64. sizeof( SOCKADDR_IN ) );
  65. }
  66. else if( pConnectionInfo->RemoteAddressType == AF_INET6 )
  67. {
  68. memcpy( &_SockRemoteAddress,
  69. &pConnectionInfo->SockRemoteAddress,
  70. sizeof( SOCKADDR_IN6 ) );
  71. }
  72. else
  73. {
  74. DBG_ASSERT( FALSE );
  75. }
  76. _RawConnectionId = pConnectionInfo->RawConnectionId;
  77. _dwSecureNotifications = 0;
  78. _dwNonSecureNotifications = 0;
  79. _fNotificationsDisabled = FALSE;
  80. _liWorkerProcessData.QuadPart = 0;
  81. _fSkipAtAll = FALSE;
  82. _dwSignature = RAW_CONNECTION_SIGNATURE;
  83. }
  84. RAW_CONNECTION::~RAW_CONNECTION()
  85. {
  86. FILTER_POOL_ITEM * pfpi;
  87. _dwSignature = RAW_CONNECTION_SIGNATURE_FREE;
  88. //
  89. // Free pool items (is most cases there won't be any since they will
  90. // have been migrated to the W3_FILTER_CONNECTION_CONTEXT)
  91. //
  92. while ( !IsListEmpty( &_PoolHead ) )
  93. {
  94. pfpi = CONTAINING_RECORD( _PoolHead.Flink,
  95. FILTER_POOL_ITEM,
  96. _ListEntry );
  97. RemoveEntryList( &pfpi->_ListEntry );
  98. delete pfpi;
  99. }
  100. //
  101. // Disconnect raw connection from main context
  102. //
  103. if ( _pMainContext != NULL )
  104. {
  105. _pMainContext->DereferenceMainContext();
  106. _pMainContext = NULL;
  107. }
  108. }
  109. //static
  110. HRESULT
  111. RAW_CONNECTION::Initialize(
  112. VOID
  113. )
  114. /*++
  115. Routine Description:
  116. Initialize ISAPI raw data filter crap
  117. Arguments:
  118. None
  119. Return Value:
  120. HRESULT
  121. --*/
  122. {
  123. DBG_ASSERT( g_pW3Server != NULL );
  124. DBG_ASSERT( sm_pRawConnectionHash == NULL );
  125. #if DBG
  126. sm_pTraceLog = CreateRefTraceLog( 2000, 0 );
  127. #endif
  128. //
  129. // Create a UL_RAW_CONNECTION_ID keyed hash table
  130. //
  131. sm_pRawConnectionHash = new RAW_CONNECTION_HASH;
  132. if ( sm_pRawConnectionHash == NULL )
  133. {
  134. return HRESULT_FROM_WIN32( GetLastError() );
  135. }
  136. return NO_ERROR;
  137. }
  138. //static
  139. VOID
  140. RAW_CONNECTION::Terminate(
  141. VOID
  142. )
  143. /*++
  144. Routine Description:
  145. Terminate raw connection hash table
  146. Arguments:
  147. None
  148. Return Value:
  149. None
  150. --*/
  151. {
  152. if ( sm_pRawConnectionHash != NULL )
  153. {
  154. delete sm_pRawConnectionHash;
  155. sm_pRawConnectionHash = NULL;
  156. }
  157. if ( sm_pTraceLog != NULL )
  158. {
  159. DestroyRefTraceLog( sm_pTraceLog );
  160. sm_pTraceLog = NULL;
  161. }
  162. }
  163. //static
  164. HRESULT
  165. RAW_CONNECTION::StopListening(
  166. VOID
  167. )
  168. /*++
  169. Routine Description:
  170. Begin shutdown by preventing further raw stream messages from UL
  171. Arguments:
  172. None
  173. Return Value:
  174. HRESULT
  175. --*/
  176. {
  177. if ( sm_fNotifyRawReadData )
  178. {
  179. IsapiFilterTerminate();
  180. }
  181. return NO_ERROR;
  182. }
  183. //static
  184. HRESULT
  185. RAW_CONNECTION::StartListening(
  186. VOID
  187. )
  188. /*++
  189. Routine Description:
  190. Start listening for stream messages from UL. Unlike UlAtqStartListen(),
  191. this routine does NOT block and will return once the initial number
  192. of outstanding UlFilterAccept() requests have been made
  193. Arguments:
  194. None
  195. Return Value:
  196. HRESULT
  197. --*/
  198. {
  199. FILTER_LIST * pFilterList;
  200. HRESULT hr;
  201. ISAPI_FILTERS_CALLBACKS sfConfig;
  202. //
  203. // Is there a read raw data filter enabled?
  204. //
  205. pFilterList = FILTER_LIST::QueryGlobalList();
  206. if ( pFilterList != NULL )
  207. {
  208. if ( pFilterList->IsNotificationNeeded( SF_NOTIFY_READ_RAW_DATA,
  209. FALSE ) )
  210. {
  211. sm_fNotifyRawReadData = TRUE;
  212. }
  213. }
  214. if ( sm_fNotifyRawReadData )
  215. {
  216. //
  217. // Now configure stream filter DLL to enable ISAPI filter
  218. // notifications
  219. //
  220. sfConfig.pfnRawRead = RAW_CONNECTION::ProcessRawRead;
  221. sfConfig.pfnRawWrite = RAW_CONNECTION::ProcessRawWrite;
  222. sfConfig.pfnConnectionClose = RAW_CONNECTION::ProcessConnectionClose;
  223. sfConfig.pfnNewConnection = RAW_CONNECTION::ProcessNewConnection;
  224. sfConfig.pfnReleaseContext = RAW_CONNECTION::ReleaseContext;
  225. hr = IsapiFilterInitialize( &sfConfig );
  226. if ( FAILED( hr ) )
  227. {
  228. //
  229. // Write event in the case if filter failed because
  230. // HTTPFilter is not running in the inetinfo.exe
  231. //
  232. g_pW3Server->LogEvent( W3_EVENT_RAW_FILTER_CANNOT_BE_STARTED_DUE_TO_HTTPFILTER,
  233. 0,
  234. NULL );
  235. sm_fNotifyRawReadData = FALSE;
  236. return hr;
  237. }
  238. }
  239. return NO_ERROR;
  240. }
  241. FILTER_LIST *
  242. RAW_CONNECTION::QueryFilterList(
  243. VOID
  244. )
  245. /*++
  246. Routine Description:
  247. Return the appropriate filter list to notify. Before a W3_CONNECTION
  248. is established, this list will simply be the global filter list. But
  249. once the W3_CONNECTION is established, the list will be the appropriate
  250. instance filter list
  251. Arguments:
  252. None
  253. Return Value:
  254. FILTER_LIST *
  255. --*/
  256. {
  257. W3_FILTER_CONTEXT * pFilterContext = NULL;
  258. FILTER_LIST * pFilterList = FILTER_LIST::QueryGlobalList();
  259. W3_MAIN_CONTEXT * pMainContext;
  260. pMainContext = GetAndReferenceMainContext();
  261. if ( pMainContext != NULL )
  262. {
  263. pFilterContext = pMainContext->QueryFilterContext();
  264. if ( pFilterContext != NULL )
  265. {
  266. pFilterList = pFilterContext->QueryFilterList();
  267. DBG_ASSERT( pFilterList != NULL );
  268. }
  269. pMainContext->DereferenceMainContext();
  270. }
  271. return pFilterList;
  272. }
  273. HRESULT
  274. RAW_CONNECTION::DisableNotification(
  275. DWORD dwNotification
  276. )
  277. /*++
  278. Routine Description:
  279. Disable notification
  280. Arguments:
  281. None
  282. Return Value:
  283. HRESULT
  284. --*/
  285. {
  286. W3_MAIN_CONTEXT * pMainContext;
  287. W3_FILTER_CONTEXT * pFilterContext;
  288. HRESULT hr = NO_ERROR;
  289. pMainContext = GetAndReferenceMainContext();
  290. if ( pMainContext != NULL )
  291. {
  292. pFilterContext = pMainContext->QueryFilterContext();
  293. if ( pFilterContext != NULL )
  294. {
  295. hr = pFilterContext->DisableNotification( dwNotification );
  296. }
  297. pMainContext->DereferenceMainContext();
  298. }
  299. else
  300. {
  301. DBG_ASSERT( QueryFilterList() != NULL );
  302. if ( !_fNotificationsDisabled )
  303. {
  304. //
  305. // All subsequent calls to IsNotificationNeeded() and NotifyFilter() must
  306. // use local copy of flags to determine action.
  307. //
  308. _fNotificationsDisabled = TRUE;
  309. //
  310. // Copy notification tables created in the FILTER_LIST objects
  311. //
  312. if ( !_BuffSecureArray.Resize( QueryFilterList()->QuerySecureArray()->QuerySize() ) ||
  313. !_BuffNonSecureArray.Resize( QueryFilterList()->QueryNonSecureArray()->QuerySize() ) )
  314. {
  315. return HRESULT_FROM_WIN32( GetLastError() );
  316. }
  317. memcpy( _BuffSecureArray.QueryPtr(),
  318. QueryFilterList()->QuerySecureArray()->QueryPtr(),
  319. QueryFilterList()->QuerySecureArray()->QuerySize() );
  320. memcpy( _BuffNonSecureArray.QueryPtr(),
  321. QueryFilterList()->QueryNonSecureArray()->QueryPtr(),
  322. QueryFilterList()->QueryNonSecureArray()->QuerySize() );
  323. }
  324. //
  325. // Disable the appropriate filter in our local table
  326. //
  327. ((DWORD*)_BuffSecureArray.QueryPtr())[ _dwCurrentFilter ] &=
  328. ~dwNotification;
  329. ((DWORD*)_BuffNonSecureArray.QueryPtr())[ _dwCurrentFilter ] &=
  330. ~dwNotification;
  331. //
  332. // Calculate the aggregate notification status for our local scenario
  333. // NYI: Might want to defer this operation?
  334. //
  335. _dwSecureNotifications = 0;
  336. _dwNonSecureNotifications = 0;
  337. for( DWORD i = 0; i < QueryFilterList()->QueryFilterCount(); i++ )
  338. {
  339. _dwSecureNotifications |= ((DWORD*)_BuffSecureArray.QueryPtr())[i];
  340. _dwNonSecureNotifications |= ((DWORD*)_BuffNonSecureArray.QueryPtr())[i];
  341. }
  342. }
  343. return hr;
  344. }
  345. BOOL
  346. RAW_CONNECTION::QueryNotificationChanged(
  347. VOID
  348. )
  349. /*++
  350. Routine Description:
  351. Returns whether or not any notifications have been disabled on the fly
  352. Arguments:
  353. None
  354. Return Value:
  355. BOOL
  356. --*/
  357. {
  358. W3_FILTER_CONTEXT * pFilterContext;
  359. W3_MAIN_CONTEXT * pMainContext;
  360. BOOL fRet = FALSE;
  361. pMainContext = GetAndReferenceMainContext();
  362. if ( pMainContext != NULL )
  363. {
  364. pFilterContext = pMainContext->QueryFilterContext();
  365. if ( pFilterContext == NULL )
  366. {
  367. fRet = FALSE;
  368. }
  369. else
  370. {
  371. fRet = pFilterContext->QueryNotificationChanged();
  372. }
  373. pMainContext->DereferenceMainContext();
  374. }
  375. else
  376. {
  377. fRet = _fNotificationsDisabled;
  378. }
  379. return fRet;
  380. }
  381. BOOL
  382. RAW_CONNECTION::QueryRawConnectionNotificationChanged(
  383. VOID
  384. )
  385. {
  386. return _fNotificationsDisabled;
  387. }
  388. BOOL
  389. RAW_CONNECTION::IsDisableNotificationNeeded(
  390. DWORD dwFilter,
  391. DWORD dwNotification
  392. )
  393. /*++
  394. Routine Description:
  395. If a notification was disabled on the fly, then this routine goes thru
  396. the notification copy path to find whether the given notification is
  397. indeed enabled
  398. Arguments:
  399. dwFilter - Filter number
  400. dwNotification - Notification to check for
  401. Return Value:
  402. BOOL (TRUE is the notification is needed)
  403. --*/
  404. {
  405. W3_MAIN_CONTEXT * pMainContext;
  406. W3_FILTER_CONTEXT * pFilterContext;
  407. BOOL fRet = FALSE;
  408. pMainContext = GetAndReferenceMainContext();
  409. if ( pMainContext != NULL )
  410. {
  411. pFilterContext = pMainContext->QueryFilterContext();
  412. DBG_ASSERT( pFilterContext != NULL );
  413. fRet = pFilterContext->IsDisableNotificationNeeded( dwFilter,
  414. dwNotification );
  415. pMainContext->DereferenceMainContext();
  416. }
  417. else
  418. {
  419. fRet = _hfc.fIsSecurePort ?
  420. ((DWORD*)_BuffSecureArray.QueryPtr())[ dwFilter ] & dwNotification :
  421. ((DWORD*)_BuffNonSecureArray.QueryPtr())[ dwFilter ] & dwNotification;
  422. fRet = !!fRet;
  423. }
  424. return fRet;
  425. }
  426. BOOL
  427. RAW_CONNECTION::IsRawConnectionDisableNotificationNeeded(
  428. DWORD dwFilter,
  429. DWORD dwNotification
  430. )
  431. {
  432. BOOL fRet;
  433. fRet = _hfc.fIsSecurePort ?
  434. ((DWORD*)_BuffSecureArray.QueryPtr())[ dwFilter ] & dwNotification :
  435. ((DWORD*)_BuffNonSecureArray.QueryPtr())[ dwFilter ] & dwNotification;
  436. fRet = !!fRet;
  437. return fRet;
  438. }
  439. PVOID
  440. RAW_CONNECTION::QueryClientContext(
  441. DWORD dwFilter
  442. )
  443. /*++
  444. Routine Description:
  445. Retrieve the filter client context for the given filter
  446. Arguments:
  447. dwFilter - Filter number
  448. Return Value:
  449. Context pointer
  450. --*/
  451. {
  452. W3_MAIN_CONTEXT * pMainContext;
  453. PVOID pvRet;
  454. //
  455. // If we have a main context associated, then use its merged context
  456. // list
  457. //
  458. pMainContext = GetAndReferenceMainContext();
  459. if ( pMainContext == NULL )
  460. {
  461. pvRet = _rgContexts[ dwFilter ];
  462. }
  463. else
  464. {
  465. pvRet = pMainContext->QueryFilterContext()->QueryClientContext( dwFilter );
  466. pMainContext->DereferenceMainContext();
  467. }
  468. return pvRet;
  469. }
  470. VOID
  471. RAW_CONNECTION::SetClientContext(
  472. DWORD dwFilter,
  473. PVOID pvContext
  474. )
  475. /*++
  476. Routine Description:
  477. Set client context for the given filter
  478. Arguments:
  479. dwFilter - Filter number
  480. pvContext - Client context
  481. Return Value:
  482. None
  483. --*/
  484. {
  485. W3_MAIN_CONTEXT * pMainContext;
  486. //
  487. // If we have a main context, use its merged context list
  488. //
  489. pMainContext = GetAndReferenceMainContext();
  490. if ( pMainContext == NULL )
  491. {
  492. _rgContexts[ dwFilter ] = pvContext;
  493. }
  494. else
  495. {
  496. pMainContext->QueryFilterContext()->SetClientContext( dwFilter,
  497. pvContext );
  498. pMainContext->DereferenceMainContext();
  499. }
  500. }
  501. VOID
  502. RAW_CONNECTION::SetLocalClientContext(
  503. DWORD dwFilter,
  504. PVOID pvContext
  505. )
  506. /*++
  507. Routine Description:
  508. Set client context for the given filter into
  509. the local array.
  510. Arguments:
  511. dwFilter - Filter number
  512. pvContext - Client context
  513. Return Value:
  514. None
  515. --*/
  516. {
  517. _rgContexts[ dwFilter ] = pvContext;
  518. }
  519. HRESULT
  520. RAW_CONNECTION::GetLimitedServerVariables(
  521. LPSTR pszVariableName,
  522. PVOID pvBuffer,
  523. PDWORD pdwSize
  524. )
  525. /*++
  526. Routine Description:
  527. Get the server variables which are possible given that we haven't parsed
  528. the HTTP request yet
  529. Arguments:
  530. pszVariableName - Variable name
  531. pvBuffer - Buffer to receive variable data
  532. pdwSize - On input size of buffer, on output the size needed
  533. Return Value:
  534. HRESULT
  535. --*/
  536. {
  537. STACK_STRA( strVariable, 256 );
  538. HRESULT hr = NO_ERROR;
  539. CHAR achNumber[ 64 ];
  540. USHORT Port;
  541. if ( pszVariableName == NULL )
  542. {
  543. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  544. }
  545. if ( strcmp( pszVariableName, "SERVER_PORT" ) == 0 ||
  546. strcmp( pszVariableName, "REMOTE_PORT" ) == 0 )
  547. {
  548. if( pszVariableName[ 0 ] == 'S' )
  549. {
  550. if( _LocalAddressType == AF_INET )
  551. {
  552. Port = ntohs( _SockLocalAddress.ipv4SockAddress.sin_port );
  553. }
  554. else if( _LocalAddressType == AF_INET6 )
  555. {
  556. Port = ntohs( _SockLocalAddress.ipv6SockAddress.sin6_port );
  557. }
  558. else
  559. {
  560. DBG_ASSERT( FALSE );
  561. }
  562. }
  563. else
  564. {
  565. if( _RemoteAddressType == AF_INET )
  566. {
  567. Port = ntohs( _SockRemoteAddress.ipv4SockAddress.sin_port );
  568. }
  569. else if( _LocalAddressType == AF_INET6 )
  570. {
  571. Port = ntohs( _SockRemoteAddress.ipv6SockAddress.sin6_port );
  572. }
  573. else
  574. {
  575. DBG_ASSERT( FALSE );
  576. }
  577. }
  578. _itoa( Port, achNumber, 10 );
  579. hr = strVariable.Copy( achNumber );
  580. }
  581. else if ( strcmp( pszVariableName, "REMOTE_ADDR" ) == 0 ||
  582. strcmp( pszVariableName, "REMOTE_HOST" ) == 0 ||
  583. strcmp( pszVariableName, "LOCAL_ADDR" ) == 0 ||
  584. strcmp( pszVariableName, "SERVER_NAME" ) == 0 )
  585. {
  586. DWORD dwAddr;
  587. SOCKADDR_IN6 IPv6Address;
  588. CHAR szNumericAddress[ NI_MAXHOST ];
  589. if( pszVariableName[ 0 ] == 'L' ||
  590. pszVariableName[ 0 ] == 'S' )
  591. {
  592. if( _LocalAddressType == AF_INET )
  593. {
  594. dwAddr = ntohl( _SockLocalAddress.ipv4SockAddress.sin_addr.s_addr );
  595. hr = TranslateIpAddressToStr( dwAddr, &strVariable );
  596. }
  597. else if( _LocalAddressType == AF_INET6 )
  598. {
  599. IPv6Address.sin6_family = AF_INET6;
  600. IPv6Address.sin6_port =
  601. _SockLocalAddress.ipv6SockAddress.sin6_port;
  602. IPv6Address.sin6_flowinfo =
  603. _SockLocalAddress.ipv6SockAddress.sin6_flowinfo;
  604. IPv6Address.sin6_addr =
  605. _SockLocalAddress.ipv6SockAddress.sin6_addr;
  606. IPv6Address.sin6_scope_id =
  607. _SockLocalAddress.ipv6SockAddress.sin6_scope_id;
  608. if( getnameinfo( ( LPSOCKADDR )&IPv6Address,
  609. sizeof( IPv6Address ),
  610. szNumericAddress,
  611. sizeof( szNumericAddress ),
  612. NULL,
  613. 0,
  614. NI_NUMERICHOST ) != 0 )
  615. {
  616. hr = HRESULT_FROM_WIN32( WSAGetLastError() );
  617. }
  618. else
  619. {
  620. hr = strVariable.Copy( szNumericAddress );
  621. }
  622. }
  623. else
  624. {
  625. DBG_ASSERT( FALSE );
  626. }
  627. }
  628. else
  629. {
  630. if( _RemoteAddressType == AF_INET )
  631. {
  632. dwAddr = ntohl( _SockRemoteAddress.ipv4SockAddress.sin_addr.s_addr );
  633. hr = TranslateIpAddressToStr( dwAddr, &strVariable );
  634. }
  635. else if( _RemoteAddressType == AF_INET6 )
  636. {
  637. IPv6Address.sin6_family = AF_INET6;
  638. IPv6Address.sin6_port =
  639. _SockRemoteAddress.ipv6SockAddress.sin6_port;
  640. IPv6Address.sin6_flowinfo =
  641. _SockRemoteAddress.ipv6SockAddress.sin6_flowinfo;
  642. IPv6Address.sin6_addr =
  643. _SockRemoteAddress.ipv6SockAddress.sin6_addr;
  644. IPv6Address.sin6_scope_id =
  645. _SockRemoteAddress.ipv6SockAddress.sin6_scope_id;
  646. if( getnameinfo( ( LPSOCKADDR )&IPv6Address,
  647. sizeof( IPv6Address ),
  648. szNumericAddress,
  649. sizeof( szNumericAddress ),
  650. NULL,
  651. 0,
  652. NI_NUMERICHOST ) != 0 )
  653. {
  654. hr = HRESULT_FROM_WIN32( WSAGetLastError() );
  655. }
  656. else
  657. {
  658. hr = strVariable.Copy( szNumericAddress );
  659. }
  660. }
  661. else
  662. {
  663. DBG_ASSERT( FALSE );
  664. }
  665. }
  666. }
  667. else if ( strcmp( pszVariableName, "HTTPS" ) == 0 )
  668. {
  669. hr = strVariable.Copy( _hfc.fIsSecurePort ? "on" : "off" );
  670. }
  671. else if ( strcmp( pszVariableName, "SERVER_PORT_SECURE" ) == 0 )
  672. {
  673. hr = strVariable.Copy( _hfc.fIsSecurePort ? "1" : "0" );
  674. }
  675. else if ( strcmp( pszVariableName, "CONTENT_LENGTH" ) == 0 )
  676. {
  677. hr = strVariable.Copy( "0" );
  678. }
  679. else if ( strcmp( pszVariableName, "SERVER_PROTOCOL" ) == 0 )
  680. {
  681. hr = strVariable.Copy( "HTTP/0.0" );
  682. }
  683. else if ( strcmp( pszVariableName, "SERVER_SOFTWARE" ) == 0 )
  684. {
  685. hr = strVariable.Copy( SERVER_SOFTWARE_STRING );
  686. }
  687. else if ( strcmp( pszVariableName, "GATEWAY_INTERFACE" ) == 0 )
  688. {
  689. hr = strVariable.Copy( "CGI/1.1" );
  690. }
  691. else
  692. {
  693. hr = strVariable.Copy( "" );
  694. }
  695. return strVariable.CopyToBuffer( (LPSTR) pvBuffer, pdwSize );
  696. }
  697. VOID
  698. RAW_CONNECTION::AddSkippedData(
  699. ULARGE_INTEGER liData
  700. )
  701. /*++
  702. Routine Description:
  703. Account for data sent by worker process (which thus should be skipped by
  704. streamfilt's filter code)
  705. Arguments:
  706. liData - Add data to be skipped
  707. Return Value:
  708. None
  709. --*/
  710. {
  711. _skipLock.WriteLock();
  712. _liWorkerProcessData.QuadPart += liData.QuadPart;
  713. _skipLock.WriteUnlock();
  714. }
  715. BOOL
  716. RAW_CONNECTION::DetermineSkippedData(
  717. DWORD cbData,
  718. DWORD * pcbOffset
  719. )
  720. /*++
  721. Routine Description:
  722. Given a streamfilt completion, determine how much has been sent by
  723. the worker process and therefore should be skipped. This function
  724. returns the amount of the data we actually want to send thru
  725. the streamfilt filter code.
  726. Arguments:
  727. cbData - Streamfilt completion
  728. pcbOffset - Points to data to be sent
  729. Return Value:
  730. BOOL - TRUE if we should send data, else FALSE
  731. --*/
  732. {
  733. BOOL fRet;
  734. _skipLock.WriteLock();
  735. if ( _liWorkerProcessData.QuadPart <= cbData )
  736. {
  737. *pcbOffset = (DWORD) cbData - _liWorkerProcessData.QuadPart;
  738. _liWorkerProcessData.QuadPart = 0;
  739. fRet = *pcbOffset != 0;
  740. }
  741. else
  742. {
  743. *pcbOffset = cbData;
  744. _liWorkerProcessData.QuadPart -= cbData;
  745. fRet = FALSE;
  746. }
  747. _skipLock.WriteUnlock();
  748. return fRet;
  749. }
  750. //static
  751. BOOL
  752. WINAPI
  753. RAW_CONNECTION::RawFilterServerSupportFunction(
  754. HTTP_FILTER_CONTEXT * pfc,
  755. enum SF_REQ_TYPE SupportFunction,
  756. void * pData,
  757. ULONG_PTR ul,
  758. ULONG_PTR ul2
  759. )
  760. /*++
  761. Routine Description:
  762. Stream filter SSF crap
  763. Arguments:
  764. pfc - Used to get back the W3_FILTER_CONTEXT and W3_MAIN_CONTEXT pointers
  765. SupportFunction - SSF to invoke (see ISAPI docs)
  766. pData, ul, ul2 - Function specific data
  767. Return Value:
  768. BOOL (use GetLastError() for error)
  769. --*/
  770. {
  771. RAW_CONNECTION * pRawConnection;
  772. HRESULT hr = NO_ERROR;
  773. BOOL fRet;
  774. //
  775. // Primitive parameter validation
  776. //
  777. if ( pfc == NULL ||
  778. pfc->ServerContext == NULL )
  779. {
  780. SetLastError( ERROR_INVALID_PARAMETER );
  781. return FALSE;
  782. }
  783. pRawConnection = (RAW_CONNECTION*) pfc->ServerContext;
  784. DBG_ASSERT( pRawConnection->CheckSignature() );
  785. switch ( SupportFunction )
  786. {
  787. case SF_REQ_SEND_RESPONSE_HEADER:
  788. hr = pRawConnection->SendResponseHeader( (CHAR*) pData,
  789. (CHAR*) ul,
  790. pfc );
  791. break;
  792. case SF_REQ_ADD_HEADERS_ON_DENIAL:
  793. hr = pRawConnection->AddDenialHeaders( (CHAR*) pData );
  794. break;
  795. case SF_REQ_SET_NEXT_READ_SIZE:
  796. pRawConnection->SetNextReadSize( (DWORD) ul );
  797. break;
  798. case SF_REQ_DISABLE_NOTIFICATIONS:
  799. hr = pRawConnection->DisableNotification( (DWORD) ul );
  800. break;
  801. default:
  802. DBG_ASSERT( FALSE );
  803. hr = HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
  804. }
  805. if ( FAILED( hr ) )
  806. {
  807. SetLastError( WIN32_FROM_HRESULT( hr ) );
  808. return FALSE;
  809. }
  810. return TRUE;
  811. }
  812. //static
  813. BOOL
  814. WINAPI
  815. RAW_CONNECTION::RawFilterGetServerVariable(
  816. HTTP_FILTER_CONTEXT * pfc,
  817. LPSTR lpszVariableName,
  818. LPVOID lpvBuffer,
  819. LPDWORD lpdwSize
  820. )
  821. /*++
  822. Routine Description:
  823. Stream filter GetServerVariable() implementation
  824. Arguments:
  825. pfc - Filter context
  826. lpszVariableName - Variable name
  827. lpvBuffer - Buffer to receive the server variable
  828. lpdwSize - On input, the size of the buffer, on output, the sized needed
  829. Return Value:
  830. BOOL (use GetLastError() for error).
  831. ERROR_INSUFFICIENT_BUFFER if larger buffer needed
  832. ERROR_INVALID_INDEX if the server variable name requested is invalid
  833. --*/
  834. {
  835. HRESULT hr = NO_ERROR;
  836. RAW_CONNECTION * pRawConnection = NULL;
  837. W3_MAIN_CONTEXT * pMainContext;
  838. //
  839. // Primitive parameter validation
  840. //
  841. if ( pfc == NULL ||
  842. pfc->ServerContext == NULL ||
  843. lpdwSize == NULL )
  844. {
  845. SetLastError( ERROR_INVALID_PARAMETER );
  846. return FALSE;
  847. }
  848. pRawConnection = (RAW_CONNECTION*) pfc->ServerContext;
  849. DBG_ASSERT( pRawConnection->CheckSignature() );
  850. //
  851. // If we have a W3_CONNECTION associated, then use its context to
  852. // get at server variables. Otherwise we can only serve the ones that
  853. // make sense
  854. //
  855. pMainContext = pRawConnection->GetAndReferenceMainContext();
  856. if ( pMainContext != NULL )
  857. {
  858. hr = SERVER_VARIABLE_HASH::GetServerVariable( pMainContext,
  859. lpszVariableName,
  860. (CHAR*) lpvBuffer,
  861. lpdwSize );
  862. pMainContext->DereferenceMainContext();
  863. }
  864. else
  865. {
  866. //
  867. // We can supply only a few (since we haven't parsed the request yet)
  868. //
  869. hr = pRawConnection->GetLimitedServerVariables( lpszVariableName,
  870. lpvBuffer,
  871. lpdwSize );
  872. }
  873. if ( FAILED( hr ) )
  874. {
  875. SetLastError( WIN32_FROM_HRESULT( hr ) );
  876. return FALSE;
  877. }
  878. return TRUE;
  879. }
  880. //static
  881. BOOL
  882. WINAPI
  883. RAW_CONNECTION::RawFilterWriteClient(
  884. HTTP_FILTER_CONTEXT * pfc,
  885. LPVOID Buffer,
  886. LPDWORD lpdwBytes,
  887. DWORD dwReserved
  888. )
  889. /*++
  890. Routine Description:
  891. Synchronous WriteClient() for stream filter
  892. Arguments:
  893. pfc - Filter context
  894. Buffer - buffer to write to client
  895. lpdwBytes - On input, the size of the input buffer. On output, the number
  896. of bytes sent
  897. dwReserved - Reserved
  898. Return Value:
  899. BOOL (use GetLastError() for error).
  900. --*/
  901. {
  902. HRESULT hr;
  903. RAW_CONNECTION * pRawConnection = NULL;
  904. PVOID pvContext;
  905. RAW_STREAM_INFO rawStreamInfo;
  906. BOOL fComplete = FALSE;
  907. //
  908. // Primitive parameter validation
  909. //
  910. if ( pfc == NULL ||
  911. pfc->ServerContext == NULL ||
  912. Buffer == NULL )
  913. {
  914. SetLastError( ERROR_INVALID_PARAMETER );
  915. return FALSE;
  916. }
  917. pRawConnection = (RAW_CONNECTION*) pfc->ServerContext;
  918. DBG_ASSERT( pRawConnection->CheckSignature() );
  919. //
  920. // Remember the filter context since calling filters will overwrite it
  921. //
  922. pvContext = pfc->pFilterContext;
  923. //
  924. // Set up the raw stream info
  925. //
  926. rawStreamInfo.pbBuffer = (BYTE*) Buffer;
  927. rawStreamInfo.cbBuffer = *lpdwBytes;
  928. rawStreamInfo.cbData = rawStreamInfo.cbBuffer;
  929. //
  930. // We need to notify all write raw data filters which are a higher
  931. // priority than the current filter
  932. //
  933. if ( pRawConnection->_dwCurrentFilter > 0 )
  934. {
  935. hr = pRawConnection->NotifyRawWriteFilters( &rawStreamInfo,
  936. &fComplete,
  937. pRawConnection->_dwCurrentFilter - 1 );
  938. if ( FAILED( hr ) )
  939. {
  940. goto Finished;
  941. }
  942. }
  943. pfc->pFilterContext = pvContext;
  944. //
  945. // Now call back into the stream filter to send the data. In transmit
  946. // SSL might do its thing with the data as well
  947. //
  948. hr = pRawConnection->_pfnSendDataBack( pRawConnection->_pvStreamContext,
  949. &rawStreamInfo );
  950. if ( FAILED( hr ) )
  951. {
  952. goto Finished;
  953. }
  954. return TRUE;
  955. Finished:
  956. if ( FAILED( hr ) )
  957. {
  958. SetLastError( WIN32_FROM_HRESULT( hr ) );
  959. return FALSE;
  960. }
  961. return TRUE;
  962. }
  963. //static
  964. VOID *
  965. WINAPI
  966. RAW_CONNECTION::RawFilterAllocateMemory(
  967. HTTP_FILTER_CONTEXT * pfc,
  968. DWORD cbSize,
  969. DWORD dwReserved
  970. )
  971. /*++
  972. Routine Description:
  973. Used by filters to allocate memory freed on connection close
  974. Arguments:
  975. pfc - Filter context
  976. cbSize - Amount to allocate
  977. dwReserved - Reserved
  978. Return Value:
  979. A pointer to the allocated memory
  980. --*/
  981. {
  982. RAW_CONNECTION * pRawConnection = NULL;
  983. //
  984. // Primitive parameter validation
  985. //
  986. if ( pfc == NULL ||
  987. pfc->ServerContext == NULL )
  988. {
  989. SetLastError( ERROR_INVALID_PARAMETER );
  990. return NULL;
  991. }
  992. pRawConnection = (RAW_CONNECTION*) pfc->ServerContext;
  993. DBG_ASSERT( pRawConnection->CheckSignature() );
  994. return pRawConnection->AllocateFilterMemory( cbSize );
  995. }
  996. //static
  997. BOOL
  998. WINAPI
  999. RAW_CONNECTION::RawFilterAddResponseHeaders(
  1000. HTTP_FILTER_CONTEXT * pfc,
  1001. LPSTR lpszHeaders,
  1002. DWORD dwReserved
  1003. )
  1004. /*++
  1005. Routine Description:
  1006. Add response headers to whatever response eventually gets sent
  1007. Arguments:
  1008. pfc - Filter context
  1009. lpszHeaders - Headers to send (\r\n delimited)
  1010. dwReserved - Reserved
  1011. Return Value:
  1012. BOOL (use GetLastError() for error).
  1013. --*/
  1014. {
  1015. HRESULT hr;
  1016. RAW_CONNECTION * pRawConnection;
  1017. W3_MAIN_CONTEXT * pMainContext = NULL;
  1018. W3_FILTER_CONTEXT * pFilterContext;
  1019. //
  1020. // Primitive parameter validation
  1021. //
  1022. if ( pfc == NULL ||
  1023. pfc->ServerContext == NULL ||
  1024. lpszHeaders == NULL )
  1025. {
  1026. SetLastError( ERROR_INVALID_PARAMETER );
  1027. return FALSE;
  1028. }
  1029. pRawConnection = (RAW_CONNECTION*) pfc->ServerContext;
  1030. DBG_ASSERT( pRawConnection->CheckSignature() );
  1031. pMainContext = pRawConnection->GetAndReferenceMainContext();
  1032. if ( pMainContext != NULL )
  1033. {
  1034. pFilterContext = pMainContext->QueryFilterContext();
  1035. DBG_ASSERT( pFilterContext != NULL );
  1036. hr = pFilterContext->AddResponseHeaders( lpszHeaders );
  1037. pMainContext->DereferenceMainContext();
  1038. }
  1039. else
  1040. {
  1041. hr = pRawConnection->AddResponseHeaders( lpszHeaders );
  1042. }
  1043. if ( FAILED( hr ) )
  1044. {
  1045. SetLastError( WIN32_FROM_HRESULT( hr ) );
  1046. return FALSE;
  1047. }
  1048. return TRUE;
  1049. }
  1050. //static
  1051. HRESULT
  1052. RAW_CONNECTION::ProcessNewConnection(
  1053. CONNECTION_INFO * pConnectionInfo,
  1054. PVOID * ppConnectionState
  1055. )
  1056. /*++
  1057. Routine Description:
  1058. Called for every new raw connection to server
  1059. Arguments:
  1060. pConnectionInfo - Information about the local/remote addresses
  1061. ppConnectionState - Connection state to be associated with raw connection
  1062. Return Value:
  1063. HRESULT
  1064. --*/
  1065. {
  1066. RAW_CONNECTION * pConnection = NULL;
  1067. LK_RETCODE lkrc;
  1068. if ( pConnectionInfo == NULL ||
  1069. ppConnectionState == NULL )
  1070. {
  1071. DBG_ASSERT( FALSE );
  1072. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  1073. }
  1074. *ppConnectionState = NULL;
  1075. //
  1076. // Try to create and add the connection
  1077. //
  1078. pConnection = new RAW_CONNECTION( pConnectionInfo );
  1079. if ( pConnection == NULL )
  1080. {
  1081. return HRESULT_FROM_WIN32( GetLastError() );
  1082. }
  1083. lkrc = sm_pRawConnectionHash->InsertRecord( pConnection );
  1084. if ( lkrc != LK_SUCCESS )
  1085. {
  1086. pConnection->DereferenceRawConnection();
  1087. pConnection = NULL;
  1088. return HRESULT_FROM_WIN32( lkrc );
  1089. }
  1090. *ppConnectionState = pConnection;
  1091. return NO_ERROR;
  1092. }
  1093. //static
  1094. HRESULT
  1095. RAW_CONNECTION::ProcessRawRead(
  1096. RAW_STREAM_INFO * pRawStreamInfo,
  1097. PVOID pContext,
  1098. BOOL * pfReadMore,
  1099. BOOL * pfComplete,
  1100. DWORD * pcbNextReadSize
  1101. )
  1102. /*++
  1103. Routine Description:
  1104. Notify ISAPI read raw data filters
  1105. Arguments:
  1106. pRawStreamInfo - The raw stream to muck with
  1107. pContext - Raw connection context
  1108. pfReadMore - Set to TRUE if we need to read more data
  1109. pfComplete - Set to TRUE if we want to disconnect client
  1110. pcbNextReadSize - Set to next read size (0 means use default size)
  1111. Return Value:
  1112. HRESULT
  1113. --*/
  1114. {
  1115. RAW_CONNECTION * pConnection = NULL;
  1116. HRESULT hr = NO_ERROR;
  1117. W3_MAIN_CONTEXT * pMainContext;
  1118. if ( pRawStreamInfo == NULL ||
  1119. pfReadMore == NULL ||
  1120. pfComplete == NULL ||
  1121. pContext == NULL ||
  1122. pcbNextReadSize == NULL )
  1123. {
  1124. DBG_ASSERT( FALSE );
  1125. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  1126. }
  1127. *pfReadMore = FALSE;
  1128. *pfComplete = FALSE;
  1129. pConnection = (RAW_CONNECTION*) pContext;
  1130. DBG_ASSERT( pConnection->CheckSignature() );
  1131. pConnection->SetNextReadSize( 0 );
  1132. //
  1133. // Synchronize access to the filter to prevent raw notifications from
  1134. // occurring at the same time as regular worker process notifications
  1135. //
  1136. pMainContext = pConnection->GetAndReferenceMainContext();
  1137. if ( pMainContext != NULL )
  1138. {
  1139. pMainContext->QueryFilterContext()->FilterLock();
  1140. }
  1141. hr = pConnection->NotifyRawReadFilters( pRawStreamInfo,
  1142. pfReadMore,
  1143. pfComplete );
  1144. if ( pMainContext != NULL )
  1145. {
  1146. pMainContext->QueryFilterContext()->FilterUnlock();
  1147. pMainContext->DereferenceMainContext();
  1148. }
  1149. *pcbNextReadSize = pConnection->QueryNextReadSize();
  1150. return hr;
  1151. }
  1152. //static
  1153. VOID
  1154. RAW_CONNECTION::ReleaseContext(
  1155. PVOID pvContext
  1156. )
  1157. /*++
  1158. Routine Description:
  1159. Release a raw connection since stream filter is done with it
  1160. Arguments:
  1161. pvContext - RAW_CONNECTION *
  1162. Return Value:
  1163. None
  1164. --*/
  1165. {
  1166. RAW_CONNECTION * pRawConnection;
  1167. pRawConnection = (RAW_CONNECTION*) pvContext;
  1168. DBG_ASSERT( pRawConnection->CheckSignature() );
  1169. pRawConnection->DereferenceRawConnection();
  1170. }
  1171. HRESULT
  1172. RAW_CONNECTION::NotifyRawReadFilters(
  1173. RAW_STREAM_INFO * pRawStreamInfo,
  1174. BOOL * pfReadMore,
  1175. BOOL * pfComplete
  1176. )
  1177. /*++
  1178. Routine Description:
  1179. Notify raw read filters
  1180. Arguments:
  1181. pRawStreamInfo - Raw stream info
  1182. pfReadMore - Set to TRUE to we should read more data
  1183. pfComplete - Set to TRUE if we should disconnect
  1184. Return Value:
  1185. HRESULT
  1186. --*/
  1187. {
  1188. HTTP_FILTER_DLL * pFilterDll;
  1189. DWORD err;
  1190. SF_STATUS_TYPE sfStatus;
  1191. DWORD i;
  1192. PVOID pvtmp;
  1193. PVOID pvCurrentClientContext;
  1194. FILTER_LIST * pFilterList;
  1195. HTTP_FILTER_RAW_DATA hfrd;
  1196. if ( pRawStreamInfo == NULL ||
  1197. pfReadMore == NULL ||
  1198. pfComplete == NULL )
  1199. {
  1200. DBG_ASSERT( FALSE );
  1201. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  1202. }
  1203. *pfComplete = FALSE;
  1204. *pfReadMore = FALSE;
  1205. //
  1206. // Setup filter raw object
  1207. //
  1208. hfrd.pvInData = pRawStreamInfo->pbBuffer;
  1209. hfrd.cbInData = pRawStreamInfo->cbData;
  1210. hfrd.cbInBuffer = pRawStreamInfo->cbBuffer;
  1211. //
  1212. // In certain cases, we can send a notification to a filter while we're still
  1213. // processing another filter's notification. In that case, we need to make sure
  1214. // we restore the current filter's context when we're done with the notifications
  1215. //
  1216. pvCurrentClientContext = _hfc.pFilterContext;
  1217. pFilterList = QueryFilterList();
  1218. DBG_ASSERT( pFilterList != NULL );
  1219. for ( i = 0; i < pFilterList->QueryFilterCount(); i++ )
  1220. {
  1221. pFilterDll = pFilterList->QueryDll( i );
  1222. //
  1223. // Notification flags are cached in the HTTP_FILTER object, but they're
  1224. // only copied from the actual HTTP_FILTER_DLL object if a filter dll
  1225. // disables a particular notification [sort of a copy-on-write scheme].
  1226. // If a filter dll disables/changes a notification, we need to check the flags
  1227. // in the HTTP_FILTER object, not those in the HTTP_FILTER_DLL object
  1228. //
  1229. if ( !QueryNotificationChanged() )
  1230. {
  1231. if ( !pFilterDll->IsNotificationNeeded( SF_NOTIFY_READ_RAW_DATA,
  1232. _hfc.fIsSecurePort ) )
  1233. {
  1234. continue;
  1235. }
  1236. }
  1237. else
  1238. {
  1239. if ( !IsDisableNotificationNeeded( i,
  1240. SF_NOTIFY_READ_RAW_DATA ) )
  1241. {
  1242. continue;
  1243. }
  1244. }
  1245. _hfc.pFilterContext = QueryClientContext( i );
  1246. pvtmp = _hfc.pFilterContext;
  1247. //
  1248. // Keep track of the current filter so that we know which filters
  1249. // to notify when a raw filter does a write client
  1250. //
  1251. _dwCurrentFilter = i;
  1252. sfStatus = (SF_STATUS_TYPE)
  1253. pFilterDll->QueryEntryPoint()( &_hfc,
  1254. SF_NOTIFY_READ_RAW_DATA,
  1255. &hfrd );
  1256. if ( pvtmp != _hfc.pFilterContext )
  1257. {
  1258. SetClientContext( i, _hfc.pFilterContext );
  1259. pFilterDll->SetHasSetContextBefore();
  1260. }
  1261. switch ( sfStatus )
  1262. {
  1263. default:
  1264. DBGPRINTF(( DBG_CONTEXT,
  1265. "Unknown status code from filter %d\n",
  1266. sfStatus ));
  1267. //
  1268. // Fall through
  1269. //
  1270. case SF_STATUS_REQ_NEXT_NOTIFICATION:
  1271. continue;
  1272. case SF_STATUS_REQ_ERROR:
  1273. _hfc.pFilterContext = pvCurrentClientContext;
  1274. return E_FAIL;
  1275. case SF_STATUS_REQ_FINISHED:
  1276. case SF_STATUS_REQ_FINISHED_KEEP_CONN: // Not supported at this point
  1277. *pfComplete = TRUE;
  1278. goto Exit;
  1279. case SF_STATUS_REQ_READ_NEXT:
  1280. *pfReadMore = TRUE;
  1281. goto Exit;
  1282. case SF_STATUS_REQ_HANDLED_NOTIFICATION:
  1283. //
  1284. // Don't notify any other filters
  1285. //
  1286. goto Exit;
  1287. }
  1288. }
  1289. Exit:
  1290. pRawStreamInfo->pbBuffer = (BYTE*) hfrd.pvInData;
  1291. pRawStreamInfo->cbData = hfrd.cbInData;
  1292. pRawStreamInfo->cbBuffer = hfrd.cbInBuffer;
  1293. //
  1294. // Reset the filter context we came in with
  1295. //
  1296. _hfc.pFilterContext = pvCurrentClientContext;
  1297. return NO_ERROR;
  1298. }
  1299. //static
  1300. HRESULT
  1301. RAW_CONNECTION::ProcessRawWrite(
  1302. RAW_STREAM_INFO * pRawStreamInfo,
  1303. PVOID pvContext,
  1304. BOOL * pfComplete
  1305. )
  1306. /*++
  1307. Routine Description:
  1308. Entry point called by stream filter to handle data coming from the
  1309. application. We will call SF_NOTIFY_SEND_RAW_DATA filter notifications
  1310. here
  1311. Arguments:
  1312. pRawStreamInfo - The stream to process, as well as an optional opaque
  1313. context set by the RAW_CONNECTION code
  1314. pvContext - Context pass back
  1315. pfComplete - Set to TRUE if we should disconnect
  1316. Return Value:
  1317. HRESULT
  1318. --*/
  1319. {
  1320. RAW_CONNECTION * pConnection = NULL;
  1321. W3_MAIN_CONTEXT * pMainContext;
  1322. HRESULT hr = NO_ERROR;
  1323. BOOL fCallFilter = FALSE;
  1324. DWORD cbOffset;
  1325. if ( pRawStreamInfo == NULL ||
  1326. pfComplete == NULL )
  1327. {
  1328. DBG_ASSERT( FALSE );
  1329. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  1330. }
  1331. *pfComplete = FALSE;
  1332. pConnection = (RAW_CONNECTION*) pvContext;
  1333. DBG_ASSERT( pConnection->CheckSignature() );
  1334. if ( pConnection->_fSkipAtAll == FALSE )
  1335. {
  1336. return NO_ERROR;
  1337. }
  1338. //
  1339. // Check whether we should just eat up these bytes
  1340. //
  1341. fCallFilter = pConnection->DetermineSkippedData( pRawStreamInfo->cbData,
  1342. &cbOffset );
  1343. if ( fCallFilter )
  1344. {
  1345. //
  1346. // Patch the buffer we send to the filter
  1347. //
  1348. pRawStreamInfo->pbBuffer = pRawStreamInfo->pbBuffer + cbOffset;
  1349. pRawStreamInfo->cbData = pRawStreamInfo->cbData - cbOffset;
  1350. hr = pConnection->NotifyRawWriteFilters( pRawStreamInfo,
  1351. pfComplete,
  1352. INVALID_DLL );
  1353. }
  1354. return hr;
  1355. }
  1356. HRESULT
  1357. RAW_CONNECTION::NotifyRawWriteFilters(
  1358. RAW_STREAM_INFO * pRawStreamInfo,
  1359. BOOL * pfComplete,
  1360. DWORD dwStartFilter
  1361. )
  1362. /*++
  1363. Routine Description:
  1364. Notify raw write filters
  1365. Arguments:
  1366. pRawStreamInfo - Raw stream to munge
  1367. pfComplete - Set to TRUE if we should disconnect now
  1368. dwStartFilter - Filter to start notifying. If this valid is INVALID_DLL,
  1369. then simply start with the lowest priority filter
  1370. Return Value:
  1371. HRESULT
  1372. --*/
  1373. {
  1374. HTTP_FILTER_DLL * pFilterDll;
  1375. DWORD err;
  1376. SF_STATUS_TYPE sfStatus;
  1377. DWORD i;
  1378. PVOID pvtmp;
  1379. PVOID pvCurrentClientContext;
  1380. FILTER_LIST * pFilterList;
  1381. HTTP_FILTER_RAW_DATA hfrd;
  1382. if ( pRawStreamInfo == NULL ||
  1383. pfComplete == NULL )
  1384. {
  1385. DBG_ASSERT( FALSE );
  1386. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  1387. }
  1388. *pfComplete = FALSE;
  1389. hfrd.pvInData = pRawStreamInfo->pbBuffer;
  1390. hfrd.cbInData = pRawStreamInfo->cbData;
  1391. hfrd.cbInBuffer = pRawStreamInfo->cbBuffer;
  1392. //
  1393. // In certain cases, we can send a notification to a filter while we're still
  1394. // processing another filter's notification. In that case, we need to make sure
  1395. // we restore the current filter's context when we're done with the notifications
  1396. //
  1397. pvCurrentClientContext = _hfc.pFilterContext;
  1398. pFilterList = QueryFilterList();
  1399. DBG_ASSERT( pFilterList != NULL );
  1400. if ( dwStartFilter == INVALID_DLL )
  1401. {
  1402. dwStartFilter = pFilterList->QueryFilterCount() - 1;
  1403. }
  1404. i = dwStartFilter;
  1405. do
  1406. {
  1407. pFilterDll = pFilterList->QueryDll( i );
  1408. //
  1409. // Notification flags are cached in the HTTP_FILTER object, but they're
  1410. // only copied from the actual HTTP_FILTER_DLL object if a filter dll
  1411. // disables a particular notification [sort of a copy-on-write scheme].
  1412. // If a filter dll disables/changes a notification, we need to check the flags
  1413. // in the HTTP_FILTER object, not those in the HTTP_FILTER_DLL object
  1414. //
  1415. if ( !QueryNotificationChanged() )
  1416. {
  1417. if ( !pFilterDll->IsNotificationNeeded( SF_NOTIFY_SEND_RAW_DATA,
  1418. _hfc.fIsSecurePort ) )
  1419. {
  1420. continue;
  1421. }
  1422. }
  1423. else
  1424. {
  1425. if ( !IsDisableNotificationNeeded( i,
  1426. SF_NOTIFY_SEND_RAW_DATA ) )
  1427. {
  1428. continue;
  1429. }
  1430. }
  1431. //
  1432. // Another slimy optimization. If this filter has never associated
  1433. // context with connection, then we don't have to do the lookup
  1434. //
  1435. _hfc.pFilterContext = QueryClientContext( i );
  1436. pvtmp = _hfc.pFilterContext;
  1437. //
  1438. // Keep track of the current filter so that we know which filters
  1439. // to notify when a raw filter does a write client
  1440. //
  1441. _dwCurrentFilter = i;
  1442. sfStatus = (SF_STATUS_TYPE)
  1443. pFilterDll->QueryEntryPoint()( &_hfc,
  1444. SF_NOTIFY_SEND_RAW_DATA,
  1445. &hfrd );
  1446. if ( pvtmp != _hfc.pFilterContext )
  1447. {
  1448. SetClientContext( i, _hfc.pFilterContext );
  1449. pFilterDll->SetHasSetContextBefore();
  1450. }
  1451. switch ( sfStatus )
  1452. {
  1453. default:
  1454. DBGPRINTF(( DBG_CONTEXT,
  1455. "Unknown status code from filter %d\n",
  1456. sfStatus ));
  1457. //
  1458. // Fall through
  1459. //
  1460. case SF_STATUS_REQ_NEXT_NOTIFICATION:
  1461. continue;
  1462. case SF_STATUS_REQ_ERROR:
  1463. _hfc.pFilterContext = pvCurrentClientContext;
  1464. return E_FAIL;
  1465. case SF_STATUS_REQ_FINISHED:
  1466. case SF_STATUS_REQ_FINISHED_KEEP_CONN: // Not supported at this point
  1467. *pfComplete = TRUE;
  1468. goto Exit;
  1469. case SF_STATUS_REQ_HANDLED_NOTIFICATION:
  1470. //
  1471. // Don't notify any other filters
  1472. //
  1473. goto Exit;
  1474. }
  1475. }
  1476. while ( i-- > 0 );
  1477. Exit:
  1478. pRawStreamInfo->pbBuffer = (BYTE*) hfrd.pvInData;
  1479. pRawStreamInfo->cbData = hfrd.cbInData;
  1480. pRawStreamInfo->cbBuffer = hfrd.cbInBuffer;
  1481. //
  1482. // Reset the filter context we came in with
  1483. //
  1484. _hfc.pFilterContext = pvCurrentClientContext;
  1485. return NO_ERROR;
  1486. }
  1487. HRESULT
  1488. RAW_CONNECTION::NotifyEndOfNetSessionFilters(
  1489. VOID
  1490. )
  1491. /*++
  1492. Routine Description:
  1493. Notify END_OF_NET_SESSION filters
  1494. Arguments:
  1495. None
  1496. Return Value:
  1497. HRESULT
  1498. --*/
  1499. {
  1500. HTTP_FILTER_DLL * pFilterDll;
  1501. DWORD err;
  1502. SF_STATUS_TYPE sfStatus;
  1503. DWORD i;
  1504. PVOID pvtmp;
  1505. PVOID pvCurrentClientContext;
  1506. FILTER_LIST * pFilterList;
  1507. HTTP_FILTER_RAW_DATA hfrd;
  1508. //
  1509. // In certain cases, we can send a notification to a filter while we're still
  1510. // processing another filter's notification. In that case, we need to make sure
  1511. // we restore the current filter's context when we're done with the notifications
  1512. //
  1513. pvCurrentClientContext = _hfc.pFilterContext;
  1514. pFilterList = QueryFilterList();
  1515. DBG_ASSERT( pFilterList != NULL );
  1516. for ( i = 0; i < pFilterList->QueryFilterCount(); i++ )
  1517. {
  1518. pFilterDll = pFilterList->QueryDll( i );
  1519. if ( !QueryNotificationChanged() )
  1520. {
  1521. if ( !pFilterDll->IsNotificationNeeded( SF_NOTIFY_END_OF_NET_SESSION,
  1522. _hfc.fIsSecurePort ) )
  1523. {
  1524. continue;
  1525. }
  1526. }
  1527. else
  1528. {
  1529. if ( !IsDisableNotificationNeeded( i,
  1530. SF_NOTIFY_END_OF_NET_SESSION ) )
  1531. {
  1532. continue;
  1533. }
  1534. }
  1535. _hfc.pFilterContext = QueryClientContext( i );
  1536. pvtmp = _hfc.pFilterContext;
  1537. //
  1538. // Keep track of the current filter so that we know which filters
  1539. // to notify when a raw filter does a write client
  1540. //
  1541. _dwCurrentFilter = i;
  1542. sfStatus = (SF_STATUS_TYPE)
  1543. pFilterDll->QueryEntryPoint()( &_hfc,
  1544. SF_NOTIFY_END_OF_NET_SESSION,
  1545. &hfrd );
  1546. if ( pvtmp != _hfc.pFilterContext )
  1547. {
  1548. SetClientContext( i, _hfc.pFilterContext );
  1549. pFilterDll->SetHasSetContextBefore();
  1550. }
  1551. switch ( sfStatus )
  1552. {
  1553. default:
  1554. DBGPRINTF(( DBG_CONTEXT,
  1555. "Unknown status code from filter %d\n",
  1556. sfStatus ));
  1557. //
  1558. // Fall through
  1559. //
  1560. case SF_STATUS_REQ_NEXT_NOTIFICATION:
  1561. continue;
  1562. case SF_STATUS_REQ_ERROR:
  1563. _hfc.pFilterContext = pvCurrentClientContext;
  1564. return E_FAIL;
  1565. case SF_STATUS_REQ_FINISHED:
  1566. case SF_STATUS_REQ_FINISHED_KEEP_CONN: // Not supported at this point
  1567. goto Exit;
  1568. case SF_STATUS_REQ_HANDLED_NOTIFICATION:
  1569. //
  1570. // Don't notify any other filters
  1571. //
  1572. goto Exit;
  1573. }
  1574. }
  1575. Exit:
  1576. //
  1577. // Reset the filter context we came in with
  1578. //
  1579. _hfc.pFilterContext = pvCurrentClientContext;
  1580. return NO_ERROR;
  1581. }
  1582. //static
  1583. VOID
  1584. RAW_CONNECTION::ProcessConnectionClose(
  1585. PVOID pvContext
  1586. )
  1587. /*++
  1588. Routine Description:
  1589. Entry point called by stream filter when a connection has closed
  1590. Arguments:
  1591. pvContext - Opaque context associated with the connection
  1592. Return Value:
  1593. None
  1594. --*/
  1595. {
  1596. RAW_CONNECTION * pRawConnection;
  1597. pRawConnection = (RAW_CONNECTION*) pvContext;
  1598. if ( pRawConnection != NULL )
  1599. {
  1600. DBG_ASSERT( pRawConnection->CheckSignature() );
  1601. //
  1602. // We're done with the raw connection. Delete it from hash table
  1603. // In the process, this will dereference the connection
  1604. //
  1605. DBG_ASSERT( sm_pRawConnectionHash != NULL );
  1606. sm_pRawConnectionHash->DeleteRecord( pRawConnection );
  1607. }
  1608. }
  1609. VOID
  1610. RAW_CONNECTION::CopyAllocatedFilterMemory(
  1611. W3_FILTER_CONTEXT * pFilterContext
  1612. )
  1613. /*++
  1614. Routine Description:
  1615. Copy over any allocated filter memory items
  1616. Arguments:
  1617. pFilterContext - Destination of filter memory item references
  1618. Return Value:
  1619. None
  1620. --*/
  1621. {
  1622. FILTER_POOL_ITEM * pfpi;
  1623. //
  1624. // We need to grab the raw connection lock since we don't want a
  1625. // read-raw data notification to muck with the pool list while we
  1626. // are copying it over to the W3_CONNECTION
  1627. //
  1628. pFilterContext->FilterLock();
  1629. while ( !IsListEmpty( &_PoolHead ) )
  1630. {
  1631. pfpi = CONTAINING_RECORD( _PoolHead.Flink,
  1632. FILTER_POOL_ITEM,
  1633. _ListEntry );
  1634. RemoveEntryList( &pfpi->_ListEntry );
  1635. InitializeListHead( &pfpi->_ListEntry );
  1636. //
  1637. // Copy the pool item to the other list
  1638. //
  1639. pFilterContext->AddFilterPoolItem( pfpi );
  1640. }
  1641. pFilterContext->FilterUnlock();
  1642. }
  1643. VOID
  1644. RAW_CONNECTION::CopyContextPointers(
  1645. W3_FILTER_CONTEXT * pFilterContext
  1646. )
  1647. /*++
  1648. Routine Description:
  1649. The global filter list is constant, in addition, when an instance filter
  1650. list is built, the global filters are always built into the list. After
  1651. the instance filter list has been identified, we need to copy any non-null
  1652. client filter context values from the global filter list to the new
  1653. positions in the instance filter list. For example:
  1654. Global List & | Instance List &
  1655. context values | new context value positions
  1656. |
  1657. G1 0 | I1 0
  1658. G2 555 | G1 0
  1659. G3 123 | G2 555
  1660. | I2 0
  1661. | G3 123
  1662. Note: This scheme precludes having the same .dll be used for both a
  1663. global and per-instance dll. Since global filters are automatically
  1664. per-instance this shouldn't be an interesting case.
  1665. --*/
  1666. {
  1667. DWORD i, j;
  1668. DWORD cGlobal;
  1669. DWORD cInstance;
  1670. HTTP_FILTER_DLL * pFilterDll;
  1671. FILTER_LIST * pGlobalFilterList;
  1672. FILTER_LIST * pInstanceFilterList;
  1673. pFilterContext->FilterLock();
  1674. DBG_ASSERT( pFilterContext != NULL );
  1675. pGlobalFilterList = FILTER_LIST::QueryGlobalList();
  1676. DBG_ASSERT( pGlobalFilterList != NULL );
  1677. cGlobal = pGlobalFilterList->QueryFilterCount();
  1678. pInstanceFilterList = pFilterContext->QueryFilterList();
  1679. DBG_ASSERT( pInstanceFilterList != NULL );
  1680. cInstance = pInstanceFilterList->QueryFilterCount();
  1681. //
  1682. // If no global filters or no instance filters, then there won't be
  1683. // any filter context pointers that need adjusting
  1684. //
  1685. if ( !cGlobal || !cInstance )
  1686. {
  1687. goto Finished;
  1688. }
  1689. //
  1690. // For each global list context pointer, find the filter in the instance
  1691. // list and adjust
  1692. //
  1693. for ( i = 0; i < cGlobal; i++ )
  1694. {
  1695. if ( _rgContexts[ i ] != NULL )
  1696. {
  1697. pFilterDll = pGlobalFilterList->QueryDll( i );
  1698. //
  1699. // We found one. Find the filter in instance list and set
  1700. //
  1701. for ( j = 0; j < cInstance; j++ )
  1702. {
  1703. if ( pInstanceFilterList->QueryDll( j ) == pFilterDll )
  1704. {
  1705. pFilterContext->SetClientContext( j, _rgContexts[ i ] );
  1706. }
  1707. }
  1708. }
  1709. }
  1710. Finished:
  1711. pFilterContext->FilterUnlock();
  1712. }
  1713. HRESULT
  1714. RAW_CONNECTION::CopyHeaders(
  1715. W3_FILTER_CONTEXT * pFilterContext
  1716. )
  1717. /*++
  1718. Routine Description:
  1719. Copy denied/response headers from read raw
  1720. Arguments:
  1721. pFilterContext - Filter context to copy to
  1722. Return Value:
  1723. HRESULT
  1724. --*/
  1725. {
  1726. HRESULT hr;
  1727. if ( pFilterContext == NULL )
  1728. {
  1729. DBG_ASSERT( FALSE );
  1730. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  1731. }
  1732. hr = pFilterContext->AddDenialHeaders( _strAddDenialHeaders.QueryStr() );
  1733. if ( FAILED( hr ) )
  1734. {
  1735. return hr;
  1736. }
  1737. hr = pFilterContext->AddResponseHeaders( _strAddResponseHeaders.QueryStr() );
  1738. if ( FAILED( hr ) )
  1739. {
  1740. return hr;
  1741. }
  1742. _strAddDenialHeaders.Reset();
  1743. _strAddResponseHeaders.Reset();
  1744. return NO_ERROR;
  1745. }
  1746. HRESULT
  1747. RAW_CONNECTION::SendResponseHeader(
  1748. CHAR * pszStatus,
  1749. CHAR * pszAdditionalHeaders,
  1750. HTTP_FILTER_CONTEXT * pfc
  1751. )
  1752. /*++
  1753. Routine Description:
  1754. Called when raw filters want to send a response header. Depending
  1755. on whether a W3_CONNECTION is associated or not, we will either
  1756. send the stream ourselves here, or call in the main context's
  1757. response facilities
  1758. Arguments:
  1759. pszStatus - ANSI status line
  1760. pszAdditionalHeaders - Any additional headers to send
  1761. pfc - Filter context (to be passed to FilterWriteClient())
  1762. Return Value:
  1763. HRESULT
  1764. --*/
  1765. {
  1766. W3_MAIN_CONTEXT * pMainContext = NULL;
  1767. STACK_STRA( strResponse, 256 );
  1768. HRESULT hr = NO_ERROR;
  1769. DWORD cbBytes = 0;
  1770. BOOL fRet = FALSE;
  1771. W3_RESPONSE * pResponse = NULL;
  1772. if ( pszStatus == NULL &&
  1773. pszAdditionalHeaders == NULL )
  1774. {
  1775. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  1776. }
  1777. //
  1778. // Which response are we touching?
  1779. //
  1780. pMainContext = GetAndReferenceMainContext();
  1781. if ( pMainContext != NULL )
  1782. {
  1783. pResponse = pMainContext->QueryResponse();
  1784. }
  1785. else
  1786. {
  1787. pResponse = &_response;
  1788. }
  1789. //
  1790. // Build up a response from what ISAPI gave us
  1791. //
  1792. hr = pResponse->BuildResponseFromIsapi( pMainContext,
  1793. pszStatus,
  1794. pszAdditionalHeaders,
  1795. pszAdditionalHeaders ?
  1796. strlen( pszAdditionalHeaders ) : 0 );
  1797. if ( FAILED( hr ) )
  1798. {
  1799. return hr;
  1800. }
  1801. //
  1802. // Now if we have a w3 context then we can send the response normally.
  1803. // Otherwise we must use the UL filter API
  1804. //
  1805. if ( pMainContext != NULL )
  1806. {
  1807. hr = pMainContext->SendResponse( W3_FLAG_SYNC |
  1808. W3_FLAG_NO_ERROR_BODY |
  1809. W3_FLAG_NO_CONTENT_LENGTH );
  1810. pMainContext->DereferenceMainContext();
  1811. }
  1812. else
  1813. {
  1814. //
  1815. // Add denial/response headers
  1816. //
  1817. if ( pResponse->QueryStatusCode() == HttpStatusUnauthorized.statusCode )
  1818. {
  1819. hr = pResponse->AppendResponseHeaders( _strAddDenialHeaders );
  1820. if ( FAILED( hr ) )
  1821. {
  1822. return hr;
  1823. }
  1824. }
  1825. hr = pResponse->AppendResponseHeaders( _strAddResponseHeaders );
  1826. if ( FAILED( hr ) )
  1827. {
  1828. return hr;
  1829. }
  1830. hr = pResponse->GetRawResponseStream( &strResponse );
  1831. if ( FAILED( hr ) )
  1832. {
  1833. return hr;
  1834. }
  1835. //
  1836. // Go thru WriteClient() so the right filtering happens on the
  1837. // response
  1838. //
  1839. cbBytes = strResponse.QueryCB();
  1840. fRet = RAW_CONNECTION::RawFilterWriteClient( pfc,
  1841. strResponse.QueryStr(),
  1842. &cbBytes,
  1843. 0 );
  1844. if ( !fRet )
  1845. {
  1846. hr = HRESULT_FROM_WIN32( GetLastError() );
  1847. }
  1848. }
  1849. return hr;
  1850. }
  1851. //static
  1852. HRESULT
  1853. RAW_CONNECTION::FindConnection(
  1854. HTTP_RAW_CONNECTION_ID rawConnectionId,
  1855. RAW_CONNECTION ** ppRawConnection
  1856. )
  1857. /*++
  1858. Routine Description:
  1859. Find and return raw connection if found
  1860. Arguments:
  1861. rawConnectionId - Raw connection ID from UL_HTTP_REQUEST
  1862. ppRawConnection - Set to raw connection if found
  1863. Return Value:
  1864. HRESULT
  1865. --*/
  1866. {
  1867. LK_RETCODE lkrc;
  1868. if ( ppRawConnection == NULL ||
  1869. rawConnectionId == HTTP_NULL_ID )
  1870. {
  1871. DBG_ASSERT( FALSE );
  1872. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  1873. }
  1874. DBG_ASSERT( sm_pRawConnectionHash != NULL );
  1875. lkrc = sm_pRawConnectionHash->FindKey( &rawConnectionId,
  1876. ppRawConnection );
  1877. if ( lkrc != LK_SUCCESS )
  1878. {
  1879. return HRESULT_FROM_WIN32( ERROR_FILE_NOT_FOUND );
  1880. }
  1881. else
  1882. {
  1883. return NO_ERROR;
  1884. }
  1885. }