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.

529 lines
12 KiB

  1. /*++
  2. Copyright (c) 1998 Microsoft Corporation
  3. Module Name :
  4. isapicontext.cxx
  5. Abstract:
  6. ISAPI stream context
  7. - used for Raw ISAPI notifications
  8. (applies only in the IIS backward compatibility mode)
  9. Author:
  10. Bilal Alam (BAlam) 29-March-2000
  11. Environment:
  12. Win32 - User Mode
  13. Project:
  14. Stream Filter Worker Process
  15. --*/
  16. #include "precomp.hxx"
  17. //static
  18. ALLOC_CACHE_HANDLER * ISAPI_STREAM_CONTEXT::sm_pachIsapiStreamContexts = NULL;
  19. PFN_PROCESS_RAW_READ ISAPI_STREAM_CONTEXT::sm_pfnRawRead;
  20. PFN_PROCESS_RAW_WRITE ISAPI_STREAM_CONTEXT::sm_pfnRawWrite;
  21. PFN_PROCESS_CONNECTION_CLOSE ISAPI_STREAM_CONTEXT::sm_pfnConnectionClose;
  22. PFN_PROCESS_NEW_CONNECTION ISAPI_STREAM_CONTEXT::sm_pfnNewConnection;
  23. PFN_RELEASE_CONTEXT ISAPI_STREAM_CONTEXT::sm_pfnReleaseContext;
  24. LIST_ENTRY ISAPI_STREAM_CONTEXT::sm_ListHead;
  25. CRITICAL_SECTION ISAPI_STREAM_CONTEXT::sm_csIsapiStreamContexts;
  26. BOOL ISAPI_STREAM_CONTEXT::sm_fInitcsIsapiStreamContexts = FALSE;
  27. LONG ISAPI_STREAM_CONTEXT::sm_lIsapiContexts = 0;
  28. BOOL ISAPI_STREAM_CONTEXT::sm_fEnabledISAPIFilters = FALSE;
  29. //static
  30. HRESULT
  31. ISAPI_STREAM_CONTEXT::Initialize(
  32. VOID
  33. )
  34. /*++
  35. Routine Description:
  36. Global initialization for ISAPI raw filtering support
  37. Arguments:
  38. pConfig - Configuration from W3CORE
  39. Return Value:
  40. HRESULT
  41. --*/
  42. {
  43. HRESULT hr = E_FAIL;
  44. InitializeListHead( &sm_ListHead );
  45. ALLOC_CACHE_CONFIGURATION acConfig;
  46. //
  47. // Setup allocation lookaside
  48. //
  49. acConfig.nConcurrency = 1;
  50. acConfig.nThreshold = 100;
  51. acConfig.cbSize = sizeof( ISAPI_STREAM_CONTEXT );
  52. DBG_ASSERT( sm_pachIsapiStreamContexts == NULL );
  53. sm_pachIsapiStreamContexts = new ALLOC_CACHE_HANDLER( "ISAPI_STREAM_CONTEXT",
  54. &acConfig );
  55. if ( sm_pachIsapiStreamContexts == NULL )
  56. {
  57. hr = HRESULT_FROM_WIN32( ERROR_NOT_ENOUGH_MEMORY );
  58. goto Finished;
  59. }
  60. BOOL fRet = InitializeCriticalSectionAndSpinCount(
  61. &sm_csIsapiStreamContexts,
  62. 0x80000000 /* precreate event */ |
  63. IIS_DEFAULT_CS_SPIN_COUNT );
  64. if ( !fRet )
  65. {
  66. hr = HRESULT_FROM_WIN32( GetLastError() );
  67. goto Finished;
  68. }
  69. sm_fInitcsIsapiStreamContexts = TRUE;
  70. hr = S_OK;
  71. Finished:
  72. if ( FAILED( hr ) )
  73. {
  74. Terminate();
  75. }
  76. return hr;
  77. }
  78. //static
  79. VOID
  80. ISAPI_STREAM_CONTEXT::Terminate(
  81. VOID
  82. )
  83. {
  84. DBG_ASSERT( !sm_fEnabledISAPIFilters );
  85. DBG_ASSERT( sm_lIsapiContexts == 0 );
  86. if ( sm_fInitcsIsapiStreamContexts )
  87. {
  88. DeleteCriticalSection( &sm_csIsapiStreamContexts );
  89. sm_fInitcsIsapiStreamContexts = FALSE;
  90. }
  91. if ( sm_pachIsapiStreamContexts != NULL )
  92. {
  93. delete sm_pachIsapiStreamContexts;
  94. sm_pachIsapiStreamContexts = NULL;
  95. }
  96. }
  97. HRESULT
  98. ISAPI_STREAM_CONTEXT::ProcessNewConnection(
  99. CONNECTION_INFO * pConnectionInfo,
  100. ENDPOINT_CONFIG * /*pEndpointConfig*/
  101. )
  102. /*++
  103. Routine Description:
  104. Handle a new raw connection
  105. Arguments:
  106. pConnectionInfo - Raw connection info
  107. Return Value:
  108. HRESULT
  109. --*/
  110. {
  111. HRESULT hr;
  112. PVOID pContext;
  113. if ( pConnectionInfo == NULL )
  114. {
  115. DBG_ASSERT( FALSE );
  116. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  117. }
  118. DBG_ASSERT( sm_pfnNewConnection != NULL );
  119. hr = sm_pfnNewConnection( pConnectionInfo,
  120. &pContext );
  121. if ( FAILED( hr ) )
  122. {
  123. return hr;
  124. }
  125. _pvContext = pContext;
  126. return NO_ERROR;
  127. }
  128. HRESULT
  129. ISAPI_STREAM_CONTEXT::ProcessRawReadData(
  130. RAW_STREAM_INFO * pRawStreamInfo,
  131. BOOL * pfReadMore,
  132. BOOL * pfComplete
  133. )
  134. /*++
  135. Routine Description:
  136. Handle data being read from the client
  137. Arguments:
  138. pRawStreamInfo - Raw stream info describing incoming data
  139. pfReadMode - Set to TRUE if we want to read more data
  140. pfComplete - Set to TRUE if we should just disconnect
  141. Return Value:
  142. HRESULT
  143. --*/
  144. {
  145. HRESULT hr;
  146. DWORD cbNextReadSize = 0;
  147. if ( pRawStreamInfo == NULL ||
  148. pfReadMore == NULL ||
  149. pfComplete == NULL )
  150. {
  151. DBG_ASSERT( FALSE );
  152. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  153. }
  154. DBG_ASSERT( sm_pfnRawRead != NULL );
  155. hr = sm_pfnRawRead( pRawStreamInfo,
  156. _pvContext,
  157. pfReadMore,
  158. pfComplete,
  159. &cbNextReadSize );
  160. if ( cbNextReadSize )
  161. {
  162. QueryFiltChannelContext()->SetNextRawReadSize( cbNextReadSize );
  163. }
  164. return hr;
  165. }
  166. HRESULT
  167. ISAPI_STREAM_CONTEXT::ProcessRawWriteData(
  168. RAW_STREAM_INFO * pRawStreamInfo,
  169. BOOL * pfComplete
  170. )
  171. /*++
  172. Routine Description:
  173. Handle data being sent to the client
  174. Arguments:
  175. pRawStreamInfo - Raw stream info describing incoming data
  176. pfComplete - Set to TRUE if we should just disconnect
  177. Return Value:
  178. HRESULT
  179. --*/
  180. {
  181. HRESULT hr;
  182. if( pRawStreamInfo == NULL ||
  183. pfComplete == NULL )
  184. {
  185. DBG_ASSERT( FALSE );
  186. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  187. }
  188. DBG_ASSERT( sm_pfnRawWrite != NULL );
  189. hr = sm_pfnRawWrite( pRawStreamInfo,
  190. _pvContext,
  191. pfComplete );
  192. return hr;
  193. }
  194. VOID
  195. ISAPI_STREAM_CONTEXT::ProcessConnectionClose(
  196. VOID
  197. )
  198. /*++
  199. Routine Description:
  200. Handle connection closure
  201. Arguments:
  202. None
  203. Return Value:
  204. HRESULT
  205. --*/
  206. {
  207. DBG_ASSERT( sm_pfnConnectionClose != NULL );
  208. sm_pfnConnectionClose( _pvContext );
  209. }
  210. //static
  211. HRESULT
  212. ISAPI_STREAM_CONTEXT::SendDataBack(
  213. PVOID pvStreamContext,
  214. RAW_STREAM_INFO * pRawStreamInfo
  215. )
  216. {
  217. FILTER_CHANNEL_CONTEXT * pFiltChannelContext;
  218. if ( pRawStreamInfo == NULL ||
  219. pvStreamContext == NULL )
  220. {
  221. DBG_ASSERT( FALSE );
  222. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  223. }
  224. pFiltChannelContext = (FILTER_CHANNEL_CONTEXT*) pvStreamContext;
  225. DBG_ASSERT( pFiltChannelContext->CheckSignature() );
  226. return pFiltChannelContext->SendDataBack( pRawStreamInfo );
  227. }
  228. //static
  229. HRESULT
  230. ISAPI_STREAM_CONTEXT::CreateContext(
  231. IN FILTER_CHANNEL_CONTEXT * pFilterChannelContext,
  232. OUT STREAM_CONTEXT ** ppIsapiContext )
  233. /*++
  234. Routine Description:
  235. Create ISAPI Context.
  236. ISAPI Contexts are to be created only in the
  237. IIS5 compatibility mode when Raw ISAPI Filter are enabled
  238. Each ISAPI context is added to the list.
  239. Upon DisableISAPIFilters() call all connections with ISAPI contexts
  240. will be closed.
  241. Arguments:
  242. pFilterChannelContext
  243. ppIsapiContext
  244. Return Value:
  245. HRESULT
  246. --*/
  247. {
  248. HRESULT hr = S_OK;
  249. DBG_ASSERT( pFilterChannelContext != NULL );
  250. ISAPI_STREAM_CONTEXT * pIsapiContext =
  251. new ISAPI_STREAM_CONTEXT( pFilterChannelContext );
  252. if ( pIsapiContext == NULL )
  253. {
  254. return HRESULT_FROM_WIN32( ERROR_OUTOFMEMORY );
  255. }
  256. EnterCriticalSection( &sm_csIsapiStreamContexts );
  257. if ( sm_fEnabledISAPIFilters )
  258. {
  259. pIsapiContext->_pFilterChannelContext = pFilterChannelContext;
  260. InsertHeadList( &sm_ListHead, &pIsapiContext->_ListEntry );
  261. sm_lIsapiContexts++;
  262. }
  263. else
  264. {
  265. //
  266. // W3SVC service must be shutting down
  267. // This is a rare path so it is OK to have it
  268. // under critical section
  269. //
  270. delete pIsapiContext;
  271. pIsapiContext = NULL;
  272. hr = HRESULT_FROM_WIN32( ERROR_SERVICE_NOT_ACTIVE );
  273. }
  274. LeaveCriticalSection( &sm_csIsapiStreamContexts );
  275. if ( SUCCEEDED( hr ) )
  276. {
  277. *ppIsapiContext = pIsapiContext;
  278. }
  279. return hr;
  280. }
  281. //static
  282. HRESULT
  283. ISAPI_STREAM_CONTEXT::EnableISAPIFilters(
  284. ISAPI_FILTERS_CALLBACKS * pCallbacks
  285. )
  286. /*++
  287. Routine Description:
  288. Enable ISAPI Filters
  289. Arguments:
  290. pCallbacks - Configuration from W3CORE
  291. Return Value:
  292. HRESULT
  293. --*/
  294. {
  295. if ( pCallbacks == NULL )
  296. {
  297. DBG_ASSERT( FALSE );
  298. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  299. }
  300. sm_pfnRawRead = pCallbacks->pfnRawRead;
  301. sm_pfnRawWrite = pCallbacks->pfnRawWrite;
  302. sm_pfnConnectionClose = pCallbacks->pfnConnectionClose;
  303. sm_pfnNewConnection = pCallbacks->pfnNewConnection;
  304. sm_pfnReleaseContext = pCallbacks->pfnReleaseContext;
  305. EnterCriticalSection( &sm_csIsapiStreamContexts );
  306. sm_fEnabledISAPIFilters = TRUE;
  307. LeaveCriticalSection( &sm_csIsapiStreamContexts );
  308. return S_OK;
  309. }
  310. //static
  311. VOID
  312. ISAPI_STREAM_CONTEXT::DisableISAPIFilters(
  313. VOID
  314. )
  315. /*++
  316. Routine Description:
  317. Trigger all connections that have ISAPI Context associated to be disconnected.
  318. Wait till all ISAPI contexts are deleted
  319. Arguments:
  320. None
  321. Return Value:
  322. HRESULT
  323. --*/
  324. {
  325. LIST_ENTRY * pCurrentEntry = NULL;
  326. LIST_ENTRY * pNextEntry = NULL;
  327. //
  328. // forcefully close all current connections that
  329. // include ISAPI filter context
  330. //
  331. //
  332. // Critical section doesn't guarantee that
  333. // Filter Channel Contexts on the list are still active
  334. // They may be in progress of being deleted waiting
  335. // to be taken out of the list. That's why caution must be
  336. // used when accessing Filter Channel Contexts
  337. //
  338. EnterCriticalSection( &sm_csIsapiStreamContexts );
  339. sm_fEnabledISAPIFilters = FALSE;
  340. pCurrentEntry = &sm_ListHead;
  341. //
  342. // Move CurrentEntry pointer to next element
  343. //
  344. pCurrentEntry = pCurrentEntry->Flink;
  345. //
  346. // Loop through each element and forcefully close all
  347. // that have ISAPI_STREAM_CONTEXT context
  348. //
  349. while( pCurrentEntry != &sm_ListHead )
  350. {
  351. ISAPI_STREAM_CONTEXT * pIsapiContext =
  352. CONTAINING_RECORD( pCurrentEntry,
  353. ISAPI_STREAM_CONTEXT,
  354. _ListEntry );
  355. pNextEntry = pCurrentEntry->Flink;
  356. //
  357. // Initiate closing of the connection
  358. // Warning: StartClose() may actually reentrantly enter
  359. // critical section and cause pIsapiContext deletion
  360. // Don't access anything in pIsapiContext or
  361. // _pFilterChannelContext after StartClose() call
  362. // Also be aware that _pFilterChannelContext may
  363. // be executing it's destructor however it's memory is still accesible
  364. // because in the worst case would block on the
  365. // sm_csIsapiStreamContexts when trying to destroy it's _pIsapiContext
  366. // Accessing _pFilterChannelContext that is partially destroyed
  367. // is ugly but under controlled circumstances it works.
  368. //
  369. pIsapiContext->QueryFilterChannelContext()->StartClose();
  370. //
  371. // Move CurrentEntry pointer to next element
  372. //
  373. pCurrentEntry = pNextEntry;
  374. }
  375. LeaveCriticalSection( &sm_csIsapiStreamContexts );
  376. //
  377. // Wait till all connections with ISAPI_STREAM_CONTEXT
  378. // are destroyed
  379. //
  380. while ( sm_lIsapiContexts != 0 )
  381. {
  382. DBGPRINTF(( DBG_CONTEXT,
  383. "Waiting for %d ISAPI CONTEXTs to drain\n",
  384. sm_lIsapiContexts ));
  385. Sleep( 1000 );
  386. }
  387. sm_pfnRawRead = NULL;
  388. sm_pfnRawWrite = NULL;
  389. sm_pfnConnectionClose = NULL;
  390. sm_pfnNewConnection = NULL;
  391. sm_pfnReleaseContext = NULL;
  392. }