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.

4566 lines
134 KiB

  1. /*++
  2. Copyright (c) 1999-2001 Microsoft Corporation
  3. Module Name :
  4. server_support.cxx
  5. Abstract:
  6. IIS Plus ServerSupportFunction command implementations
  7. Author:
  8. Wade Hilmo (wadeh) 05-Apr-2000
  9. Project:
  10. w3isapi.dll
  11. --*/
  12. #include "precomp.hxx"
  13. #include "isapi_context.hxx"
  14. #include "server_support.hxx"
  15. //
  16. // BUGBUG - stristr is declared in iisrearc\core\inc\irtlmisc.h,
  17. // but doesn't appear to be implemented anywhere. Because of the
  18. // way it's declared in that file, we have to use a different
  19. // function name here...
  20. //
  21. const char*
  22. stristr2(
  23. const char* pszString,
  24. const char* pszSubString
  25. );
  26. HRESULT
  27. SSFSendResponseHeader(
  28. ISAPI_CONTEXT * pIsapiContext,
  29. LPSTR szStatus,
  30. LPSTR szHeaders
  31. )
  32. /*++
  33. Routine Description:
  34. Sends HTTP status and headers to the client.
  35. Arguments:
  36. pIsapiContext - The ISAPI_CONTEXT associated with this command.
  37. szStatus - The status to send to the client (ie. "200 OK")
  38. szHeaders - Headers to send to the client (ie. foo1: value1\r\n\r\n")
  39. Return Value:
  40. HRESULT
  41. --*/
  42. {
  43. IIsapiCore * pIsapiCore;
  44. HRESULT hr;
  45. DBG_ASSERT( pIsapiContext );
  46. DBG_ASSERT( pIsapiContext->CheckSignature() );
  47. IF_DEBUG( ISAPI_SSF_DETAILS )
  48. {
  49. DBGPRINTF(( DBG_CONTEXT,
  50. "\r\n"
  51. " HSE_REQ_SEND_RESPONSE_HEADER[%p]: Function Entry\r\n"
  52. " Status: '%s'\r\n"
  53. " Headers: '%s'\r\n"
  54. " <END>\r\n\r\n",
  55. pIsapiContext,
  56. szStatus,
  57. szHeaders ));
  58. }
  59. pIsapiCore = pIsapiContext->QueryIsapiCoreInterface();
  60. if ( pIsapiCore == NULL )
  61. {
  62. IF_DEBUG( ISAPI_ERROR_RETURNS )
  63. {
  64. DBGPRINTF(( DBG_CONTEXT,
  65. "\r\n"
  66. " HSE_REQ_SEND_RESPONSE_HEADER[%p]: Failed to get interface to server core\r\n"
  67. " <END>\r\n\r\n",
  68. pIsapiContext ));
  69. }
  70. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  71. }
  72. //
  73. // We need validate the fKeepConn status for the request now,
  74. // since http.sys will generate the connection response
  75. // header based on it.
  76. //
  77. // If we're going to support keep-alive, then the
  78. // ISAPI must return either a content-length header,
  79. // or use chunked transfer encoding. We'll check for
  80. // that here.
  81. //
  82. if ( pIsapiContext->QueryClientKeepConn() )
  83. {
  84. if ( szHeaders != NULL &&
  85. ( stristr2( szHeaders, "content-length: " ) != NULL ||
  86. stristr2( szHeaders, "transfer-encoding: chunked" ) != NULL ) )
  87. {
  88. pIsapiContext->SetKeepConn( TRUE );
  89. }
  90. }
  91. //
  92. // Since we automatically decided to keep the connection alive
  93. // or not, we should not honor HSE_STATUS_SUCCESS_AND_KEEP_CONN.
  94. // This maintains compatibility with previous IIS versions.
  95. //
  96. pIsapiContext->SetHonorAndKeepConn( FALSE );
  97. //
  98. // Note that NULL is valid for both szStatus and szHeaders,
  99. // so there's no need to validate them.
  100. //
  101. hr = pIsapiCore->SendResponseHeaders(
  102. !pIsapiContext->QueryKeepConn(),
  103. szStatus,
  104. szHeaders,
  105. HSE_IO_SYNC
  106. );
  107. if ( FAILED( hr ) )
  108. {
  109. IF_DEBUG( ISAPI_ERROR_RETURNS )
  110. {
  111. DBGPRINTF(( DBG_CONTEXT,
  112. "\r\n"
  113. " HSE_REQ_SEND_RESPONSE_HEADER[%p]: Failed\r\n"
  114. " Error: 0x%08x\r\n"
  115. " <END>\r\n\r\n",
  116. pIsapiContext,
  117. hr ));
  118. }
  119. return hr;
  120. }
  121. else
  122. {
  123. pIsapiContext->SetHeadersSent( TRUE );
  124. }
  125. IF_DEBUG( ISAPI_SSF_DETAILS )
  126. {
  127. IF_DEBUG( ISAPI_SUCCESS_RETURNS )
  128. {
  129. DBGPRINTF(( DBG_CONTEXT,
  130. "\r\n"
  131. " HSE_REQ_SEND_RESPONSE_HEADER[%p]: Succeeded\r\n"
  132. " <END>\r\n\r\n",
  133. pIsapiContext ));
  134. }
  135. }
  136. return hr;
  137. }
  138. HRESULT
  139. SSFSendResponseHeaderEx(
  140. ISAPI_CONTEXT * pIsapiContext,
  141. HSE_SEND_HEADER_EX_INFO * pHeaderInfo
  142. )
  143. /*++
  144. Routine Description:
  145. Sends HTTP status and headers to the client, and offers
  146. explicit control over keep-alive for this request.
  147. Arguments:
  148. pIsapiContext - The ISAPI_CONTEXT associated with this command.
  149. pHeaderInfo - The response info to be passed to the client
  150. Return Value:
  151. HRESULT
  152. --*/
  153. {
  154. IIsapiCore * pIsapiCore;
  155. HRESULT hr;
  156. DBG_ASSERT( pIsapiContext );
  157. DBG_ASSERT( pIsapiContext->CheckSignature() );
  158. IF_DEBUG( ISAPI_SSF_DETAILS )
  159. {
  160. DBGPRINTF(( DBG_CONTEXT,
  161. "\r\n"
  162. " HSE_REQ_SEND_RESPONSE_HEADER_EX[%p]: Function Entry\r\n"
  163. " Status: '%s'\r\n"
  164. " Headers: '%s'\r\n"
  165. " KeepConn: %d\r\n",
  166. pIsapiContext,
  167. pHeaderInfo->pszStatus,
  168. pHeaderInfo->pszHeader,
  169. pHeaderInfo->fKeepConn ));
  170. }
  171. pIsapiCore = pIsapiContext->QueryIsapiCoreInterface();
  172. if ( pIsapiCore == NULL )
  173. {
  174. IF_DEBUG( ISAPI_ERROR_RETURNS )
  175. {
  176. DBGPRINTF(( DBG_CONTEXT,
  177. "\r\n"
  178. " HSE_REQ_SEND_RESPONSE_HEADER_EX[%p]: Failed to get interface to server core\r\n"
  179. " <END>\r\n\r\n",
  180. pIsapiContext ));
  181. }
  182. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  183. }
  184. //
  185. // Validate parameters
  186. //
  187. if ( pHeaderInfo == NULL )
  188. {
  189. IF_DEBUG( ISAPI_ERROR_RETURNS )
  190. {
  191. DBGPRINTF(( DBG_CONTEXT,
  192. "\r\n"
  193. " HSE_REQ_SEND_RESPONSE_HEADER_EX[%p]: Parameter validation failure\r\n"
  194. " pHeaderInfo: NULL\r\n"
  195. " <END>\r\n\r\n",
  196. pIsapiContext ));
  197. }
  198. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  199. }
  200. //
  201. // Set the keep connection flag. It can only be TRUE if the
  202. // ISAPI and the client both want keep alive.
  203. //
  204. // Note that we are trusting the ISAPI to provide some kind
  205. // of content length in the case where it's setting fKeepConn
  206. // to TRUE. This is the same behavior as IIS 5 which, for
  207. // performance reasons, doesn't try to parse the headers from
  208. // the ISAPI.
  209. //
  210. if ( pHeaderInfo->fKeepConn &&
  211. pIsapiContext->QueryClientKeepConn() )
  212. {
  213. pIsapiContext->SetKeepConn( TRUE );
  214. }
  215. hr = pIsapiCore->SendResponseHeaders(
  216. !pIsapiContext->QueryKeepConn(),
  217. const_cast<LPSTR>( pHeaderInfo->pszStatus ),
  218. const_cast<LPSTR>( pHeaderInfo->pszHeader ),
  219. HSE_IO_SYNC
  220. );
  221. if ( FAILED( hr ) )
  222. {
  223. IF_DEBUG( ISAPI_ERROR_RETURNS )
  224. {
  225. DBGPRINTF(( DBG_CONTEXT,
  226. "\r\n"
  227. " HSE_REQ_SEND_RESPONSE_HEADER_EX[%p]: Failed.\r\n"
  228. " Error: 0x%08x\r\n"
  229. " <END>\r\n\r\n",
  230. pIsapiContext,
  231. hr ));
  232. }
  233. return hr;
  234. }
  235. else
  236. {
  237. pIsapiContext->SetHeadersSent( TRUE );
  238. }
  239. IF_DEBUG( ISAPI_SSF_DETAILS )
  240. {
  241. IF_DEBUG( ISAPI_SUCCESS_RETURNS )
  242. {
  243. DBGPRINTF(( DBG_CONTEXT,
  244. "\r\n"
  245. " HSE_REQ_SEND_RESPONSE_HEADER_EX[%p]: Succeeded\r\n"
  246. " <END>\r\n",
  247. pIsapiContext ));
  248. }
  249. }
  250. return hr;
  251. }
  252. HRESULT
  253. SSFMapUrlToPath(
  254. ISAPI_CONTEXT * pIsapiContext,
  255. LPSTR szBuffer,
  256. LPDWORD pcbBuffer
  257. )
  258. /*++
  259. Routine Description:
  260. Maps a URL into a physical path
  261. Arguments:
  262. pIsapiContext - The ISAPI_CONTEXT associated with this command.
  263. szBuffer - On entry, contains the URL to map. On return,
  264. contains the mapped physical path.
  265. pcbBuffer - On entry, the size of szBuffer. On successful
  266. return, the number of bytes copied to szUrl. On
  267. failed return, the number of bytes needed for the
  268. physical path.
  269. Return Value:
  270. HRESULT
  271. --*/
  272. {
  273. IIsapiCore * pIsapiCore;
  274. HRESULT hr;
  275. DBG_ASSERT( pIsapiContext );
  276. DBG_ASSERT( pIsapiContext->CheckSignature() );
  277. IF_DEBUG( ISAPI_SSF_DETAILS )
  278. {
  279. DBGPRINTF(( DBG_CONTEXT,
  280. "\r\n"
  281. " HSE_REQ_MAP_URL_TO_PATH[%p]: Function Entry\r\n"
  282. " URL: %s\r\n"
  283. " <END>\r\n\r\n",
  284. pIsapiContext,
  285. szBuffer ));
  286. }
  287. pIsapiCore = pIsapiContext->QueryIsapiCoreInterface();
  288. if ( pIsapiCore == NULL )
  289. {
  290. IF_DEBUG( ISAPI_ERROR_RETURNS )
  291. {
  292. DBGPRINTF(( DBG_CONTEXT,
  293. "\r\n"
  294. " HSE_REQ_MAP_URL_TO_PATH[%p]: Failed to get interface to server core\r\n"
  295. " <END>\r\n\r\n",
  296. pIsapiContext ));
  297. }
  298. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  299. }
  300. //
  301. // Validate parameters
  302. //
  303. if ( szBuffer == NULL ||
  304. pcbBuffer == NULL ||
  305. *pcbBuffer == 0 )
  306. {
  307. IF_DEBUG( ISAPI_ERROR_RETURNS )
  308. {
  309. DBGPRINTF(( DBG_CONTEXT,
  310. "\r\n"
  311. " HSE_REQ_MAP_URL_TO_PATH[%p]: Parameter validation failure\r\n"
  312. " Buffer: '%s'\r\n"
  313. " Buffer Size Ptr: %p\r\n"
  314. " Buffer Size: %d\r\n",
  315. pIsapiContext,
  316. pcbBuffer,
  317. pcbBuffer ? *pcbBuffer : 0 ));
  318. }
  319. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  320. }
  321. hr = pIsapiCore->MapPath(
  322. reinterpret_cast<BYTE*>( szBuffer ),
  323. *pcbBuffer,
  324. pcbBuffer,
  325. FALSE
  326. );
  327. if ( FAILED( hr ) )
  328. {
  329. IF_DEBUG( ISAPI_ERROR_RETURNS )
  330. {
  331. DBGPRINTF(( DBG_CONTEXT,
  332. "\r\n"
  333. " HSE_REQ_MAP_URL_TO_PATH[%p]: Failed\r\n"
  334. " Error: 0x%08x\r\n"
  335. " <END>\r\n\r\n",
  336. pIsapiContext,
  337. hr ));
  338. }
  339. return hr;
  340. }
  341. IF_DEBUG( ISAPI_SSF_DETAILS )
  342. {
  343. IF_DEBUG( ISAPI_SUCCESS_RETURNS )
  344. {
  345. DBGPRINTF(( DBG_CONTEXT,
  346. "\r\n"
  347. " HSE_REQ_MAP_URL_TO_PATH[%p]: Succeeded\r\n"
  348. " Mapped URL: %s\r\n"
  349. " <END>\r\n\r\n",
  350. pIsapiContext,
  351. szBuffer ));
  352. }
  353. }
  354. return hr;
  355. }
  356. HRESULT
  357. SSFMapUrlToPathEx(
  358. ISAPI_CONTEXT * pIsapiContext,
  359. LPSTR szUrl,
  360. HSE_URL_MAPEX_INFO * pHseMapInfo,
  361. LPDWORD pcbMappedPath
  362. )
  363. /*++
  364. Routine Description:
  365. Maps a URL to a physical path and returns some metadata
  366. metrics for the URL to the caller.
  367. Arguments:
  368. pIsapiContext - The ISAPI_CONTEXT associated with this command.
  369. szUrl - The URL to map
  370. pHseMapInfo - Upon return, contains the mapped URL info
  371. pcbMappedPath - If non-NULL, contains the buffer size needed
  372. to store the mapped physical path.
  373. Return Value:
  374. HRESULT
  375. --*/
  376. {
  377. IIsapiCore * pIsapiCore;
  378. DWORD cbMapped;
  379. HRESULT hr;
  380. DBG_ASSERT( pIsapiContext );
  381. DBG_ASSERT( pIsapiContext->CheckSignature() );
  382. IF_DEBUG( ISAPI_SSF_DETAILS )
  383. {
  384. DBGPRINTF(( DBG_CONTEXT,
  385. "\r\n"
  386. " HSE_REQ_MAP_URL_TO_PATH_EX[%p]: Function Entry\r\n"
  387. " URL='%s'\r\n"
  388. " <END>\r\n\r\n",
  389. pIsapiContext,
  390. szUrl ));
  391. }
  392. pIsapiCore = pIsapiContext->QueryIsapiCoreInterface();
  393. if ( pIsapiCore == NULL )
  394. {
  395. IF_DEBUG( ISAPI_ERROR_RETURNS )
  396. {
  397. DBGPRINTF(( DBG_CONTEXT,
  398. "\r\n"
  399. " HSE_REQ_MA_URL_TO_PATH_EX[%p]: Failed to get interface to server core\r\n"
  400. " <END>\r\n\r\n",
  401. pIsapiContext ));
  402. }
  403. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  404. }
  405. //
  406. // Additional parameter validation
  407. //
  408. if ( szUrl == NULL ||
  409. pHseMapInfo == NULL )
  410. {
  411. IF_DEBUG( ISAPI_ERROR_RETURNS )
  412. {
  413. DBGPRINTF(( DBG_CONTEXT,
  414. "\r\n"
  415. " HSE_REQ_MAP_URL_TO_PATH_EX[%p]: Parameter validation failure\r\n"
  416. " URL: '%s'\r\n"
  417. " HSE_URL_MAPEX_INFO: %p\r\n"
  418. " <END>\r\n\r\n",
  419. pIsapiContext,
  420. szUrl,
  421. pHseMapInfo ));
  422. }
  423. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  424. }
  425. //
  426. // The inline buffer within the HSE_URL_MAPEX_INFO structure
  427. // is defined as being MAX_PATH size.
  428. //
  429. cbMapped = MAX_PATH;
  430. pHseMapInfo->dwReserved1 = 0;
  431. pHseMapInfo->dwReserved2 = 0;
  432. hr = pIsapiCore->MapPathEx(
  433. reinterpret_cast<BYTE*>( szUrl ),
  434. (DWORD)strlen(szUrl) + 1,
  435. reinterpret_cast<BYTE*>( pHseMapInfo->lpszPath ),
  436. cbMapped,
  437. pcbMappedPath ? pcbMappedPath : &cbMapped,
  438. &pHseMapInfo->cchMatchingPath,
  439. &pHseMapInfo->cchMatchingURL,
  440. &pHseMapInfo->dwFlags,
  441. FALSE
  442. );
  443. if ( FAILED( hr ) )
  444. {
  445. IF_DEBUG( ISAPI_ERROR_RETURNS )
  446. {
  447. DBGPRINTF(( DBG_CONTEXT,
  448. "\r\n"
  449. " HSE_REQ_MAP_URL_TO_PATH_EX[%p]: Failed\r\n"
  450. " Error: 0x%08x\r\n"
  451. " <END>\r\n\r\n",
  452. pIsapiContext,
  453. hr ));
  454. }
  455. return hr;
  456. }
  457. return hr;
  458. }
  459. HRESULT
  460. SSFMapUnicodeUrlToPath(
  461. ISAPI_CONTEXT * pIsapiContext,
  462. LPWSTR szBuffer,
  463. LPDWORD pcbBuffer
  464. )
  465. /*++
  466. Routine Description:
  467. Maps a URL into a physical path
  468. Arguments:
  469. pIsapiContext - The ISAPI_CONTEXT associated with this command.
  470. szBuffer - On entry, contains the URL to map. On return,
  471. contains the mapped physical path.
  472. pcbBuffer - On entry, the size of szBuffer. On successful
  473. return, the number of bytes copied to szUrl. On
  474. failed return, the number of bytes needed for the
  475. physical path.
  476. Return Value:
  477. HRESULT
  478. --*/
  479. {
  480. IIsapiCore * pIsapiCore;
  481. HRESULT hr;
  482. DBG_ASSERT( pIsapiContext );
  483. DBG_ASSERT( pIsapiContext->CheckSignature() );
  484. IF_DEBUG( ISAPI_SSF_DETAILS )
  485. {
  486. DBGPRINTF(( DBG_CONTEXT,
  487. "\r\n"
  488. " HSE_REQ_MAP_UNICODE_URL_TO_PATH[%p]: Function Entry\r\n"
  489. " URL='%S'\r\n"
  490. " <END>\r\n\r\n",
  491. pIsapiContext,
  492. szBuffer ));
  493. }
  494. pIsapiCore = pIsapiContext->QueryIsapiCoreInterface();
  495. if ( pIsapiCore == NULL )
  496. {
  497. IF_DEBUG( ISAPI_ERROR_RETURNS )
  498. {
  499. DBGPRINTF(( DBG_CONTEXT,
  500. "\r\n"
  501. " HSE_REQ_MA_UNICODE_URL_TO_PATH[%p]: Failed to get interface to server core\r\n"
  502. " <END>\r\n\r\n",
  503. pIsapiContext ));
  504. }
  505. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  506. }
  507. //
  508. // Validate parameters
  509. //
  510. if ( szBuffer == NULL ||
  511. pcbBuffer == NULL ||
  512. *pcbBuffer == 0 )
  513. {
  514. IF_DEBUG( ISAPI_ERROR_RETURNS )
  515. {
  516. DBGPRINTF(( DBG_CONTEXT,
  517. "\r\n"
  518. " HSE_REQ_MAP_UNICODE_URL_TO_PATH[%p]: Parameter validation failure\r\n"
  519. " Buffer: '%S'\r\n"
  520. " Buffer Size Ptr: %p\r\n"
  521. " Buffer Size: %d\r\n"
  522. " <END>\r\n\r\n",
  523. pIsapiContext,
  524. szBuffer,
  525. pcbBuffer,
  526. pcbBuffer ? *pcbBuffer : 0 ));
  527. }
  528. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  529. }
  530. hr = pIsapiCore->MapPath(
  531. reinterpret_cast<BYTE*>( szBuffer ),
  532. *pcbBuffer,
  533. pcbBuffer,
  534. TRUE
  535. );
  536. if ( FAILED( hr ) )
  537. {
  538. IF_DEBUG( ISAPI_ERROR_RETURNS )
  539. {
  540. DBGPRINTF(( DBG_CONTEXT,
  541. "\r\n"
  542. " HSE_REQ_MAP_UNICODE_URL_TO_PATH[%p]: Failed\r\n"
  543. " Error: 0x%08x\r\n"
  544. " <END>\r\n\r\n",
  545. pIsapiContext,
  546. hr ));
  547. }
  548. return hr;
  549. }
  550. return hr;
  551. }
  552. HRESULT
  553. SSFMapUnicodeUrlToPathEx(
  554. ISAPI_CONTEXT * pIsapiContext,
  555. LPWSTR szUrl,
  556. HSE_UNICODE_URL_MAPEX_INFO *pHseMapInfo,
  557. LPDWORD pcbMappedPath
  558. )
  559. /*++
  560. Routine Description:
  561. Maps a URL to a physical path and returns some metadata
  562. metrics for the URL to the caller.
  563. Arguments:
  564. pIsapiContext - The ISAPI_CONTEXT associated with this command.
  565. szUrl - The URL to map
  566. pHseMapInfo - Upon return, contains the mapped URL info
  567. pcbMappedPath - If non-NULL, contains the buffer size needed
  568. to store the mapped physical path.
  569. Return Value:
  570. HRESULT
  571. --*/
  572. {
  573. IIsapiCore * pIsapiCore;
  574. DWORD cbMapped;
  575. HRESULT hr;
  576. DBG_ASSERT( pIsapiContext );
  577. DBG_ASSERT( pIsapiContext->CheckSignature() );
  578. IF_DEBUG( ISAPI_SSF_DETAILS )
  579. {
  580. DBGPRINTF(( DBG_CONTEXT,
  581. "\r\n"
  582. " HSE_REQ_MAP_UNICODE_URL_TO_PATH_EX[%p]: Function Entry\r\n"
  583. " URL='%S'\r\n"
  584. " <END>\r\n\r\n",
  585. pIsapiContext,
  586. szUrl ));
  587. }
  588. pIsapiCore = pIsapiContext->QueryIsapiCoreInterface();
  589. if ( pIsapiCore == NULL )
  590. {
  591. IF_DEBUG( ISAPI_ERROR_RETURNS )
  592. {
  593. DBGPRINTF(( DBG_CONTEXT,
  594. "\r\n"
  595. " HSE_REQ_MA_UNICODE_URL_TO_PATH_EX[%p]: Failed to get interface to server core\r\n"
  596. " <END>\r\n\r\n",
  597. pIsapiContext ));
  598. }
  599. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  600. }
  601. //
  602. // Additional parameter validation
  603. //
  604. if ( szUrl == NULL ||
  605. pHseMapInfo == NULL )
  606. {
  607. IF_DEBUG( ISAPI_ERROR_RETURNS )
  608. {
  609. DBGPRINTF(( DBG_CONTEXT,
  610. "\r\n"
  611. " HSE_REQ_MAP_UNICODE_URL_TO_PATH_EX[%p]: Parameter validation failure\r\n"
  612. " URL: '%s'\r\n"
  613. " pHseMapInfo: %p\r\n"
  614. " <END>\r\n\r\n",
  615. pIsapiContext,
  616. szUrl,
  617. pHseMapInfo ));
  618. }
  619. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  620. }
  621. //
  622. // The inline buffer within the HSE_URL_MAPEX_INFO structure
  623. // is defined as being MAX_PATH size.
  624. //
  625. cbMapped = MAX_PATH * sizeof(WCHAR);
  626. hr = pIsapiCore->MapPathEx(
  627. reinterpret_cast<BYTE*>( szUrl ),
  628. (DWORD)(wcslen(szUrl) + 1)*sizeof(WCHAR),
  629. reinterpret_cast<BYTE*>( pHseMapInfo->lpszPath ),
  630. cbMapped,
  631. pcbMappedPath ? pcbMappedPath : &cbMapped,
  632. &pHseMapInfo->cchMatchingPath,
  633. &pHseMapInfo->cchMatchingURL,
  634. &pHseMapInfo->dwFlags,
  635. TRUE
  636. );
  637. if ( FAILED( hr ) )
  638. {
  639. IF_DEBUG( ISAPI_ERROR_RETURNS )
  640. {
  641. DBGPRINTF(( DBG_CONTEXT,
  642. "\r\n"
  643. " HSE_REQ_MAP_UNICODE_URL_TO_PATH_EX[%p]: Failed\r\n"
  644. " Error: 0x%08x\r\n"
  645. " <END>\r\n\r\n",
  646. pIsapiContext,
  647. hr ));
  648. }
  649. return hr;
  650. }
  651. return hr;
  652. }
  653. HRESULT
  654. SSFGetImpersonationToken(
  655. ISAPI_CONTEXT * pIsapiContext,
  656. HANDLE * phToken
  657. )
  658. /*++
  659. Routine Description:
  660. Returns a (non-duplicated) copy of the token that the server
  661. is using to impersonate the client for this request.
  662. Arguments:
  663. pIsapiContext - The ISAPI_CONTEXT associated with this command.
  664. phToken - Upon return, contains a copy of the token.
  665. Return Value:
  666. HRESULT
  667. --*/
  668. {
  669. DBG_ASSERT( pIsapiContext );
  670. DBG_ASSERT( pIsapiContext->CheckSignature() );
  671. IF_DEBUG( ISAPI_SSF_DETAILS )
  672. {
  673. DBGPRINTF(( DBG_CONTEXT,
  674. "\r\n"
  675. " HSE_REQ_GET_IMPERSONATION_TOKEN[%p]: Function Entry\r\n"
  676. " <END>\r\n\r\n",
  677. pIsapiContext ));
  678. }
  679. //
  680. // Validate parameters
  681. //
  682. if ( phToken == NULL )
  683. {
  684. IF_DEBUG( ISAPI_ERROR_RETURNS )
  685. {
  686. DBGPRINTF(( DBG_CONTEXT,
  687. "\r\n"
  688. " HSE_REQ_GET_IMPERSONATION_TOKEN[%p]: Parameter validation failure\r\n"
  689. " Token Ptr: NULL\r\n"
  690. " <END>\r\n\r\n",
  691. pIsapiContext ));
  692. }
  693. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  694. }
  695. *phToken = pIsapiContext->QueryToken();
  696. return NO_ERROR;
  697. }
  698. HRESULT
  699. SSFIsKeepConn(
  700. ISAPI_CONTEXT * pIsapiContext,
  701. BOOL * pfIsKeepAlive
  702. )
  703. /*++
  704. Routine Description:
  705. Returns information about whether the client wants us to keep
  706. the connection open or not at completion of this request.
  707. Arguments:
  708. pIsapiContext - The ISAPI_CONTEXT associated with this command.
  709. pfIsKeepAlive - Upon return, TRUE if IIS will be keeping the
  710. connection alive, else FALSE.
  711. Return Value:
  712. HRESULT
  713. --*/
  714. {
  715. DBG_ASSERT( pIsapiContext );
  716. DBG_ASSERT( pIsapiContext->CheckSignature() );
  717. IF_DEBUG( ISAPI_SSF_DETAILS )
  718. {
  719. DBGPRINTF(( DBG_CONTEXT,
  720. "\r\n"
  721. " HSE_REQ_IS_KEEP_CONN[%p]: Function Entry\r\n"
  722. " <END>\r\n\r\n",
  723. pIsapiContext ));
  724. }
  725. //
  726. // Validate parameters
  727. //
  728. if ( pfIsKeepAlive == NULL )
  729. {
  730. IF_DEBUG( ISAPI_ERROR_RETURNS )
  731. {
  732. DBGPRINTF(( DBG_CONTEXT,
  733. "\r\n"
  734. " HSE_REQ_IS_KEEP_CONN[%p]: Parameter validation failure\r\n"
  735. " KeepAlive Ptr: NULL\r\n"
  736. " <END>\r\n\r\n",
  737. pIsapiContext ));
  738. }
  739. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  740. }
  741. *pfIsKeepAlive = pIsapiContext->QueryClientKeepConn();
  742. return NO_ERROR;
  743. }
  744. HRESULT
  745. SSFDoneWithSession(
  746. ISAPI_CONTEXT * pIsapiContext,
  747. DWORD * pHseResult
  748. )
  749. /*++
  750. Routine Description:
  751. Notifies the server that the calling ISAPI is done with the
  752. ECB (and ISAPI_CONTEXT) for this request and that the server
  753. can clean up.
  754. Arguments:
  755. pIsapiContext - The ISAPI_CONTEXT associated with this command.
  756. pHseResult - A pointer to the HSE_STATUS code that the extension
  757. wants to use.
  758. Return Value:
  759. HRESULT
  760. --*/
  761. {
  762. IIsapiCore * pIsapiCore;
  763. DBG_ASSERT( pIsapiContext );
  764. DBG_ASSERT( pIsapiContext->CheckSignature() );
  765. DBG_ASSERT( pIsapiContext->QueryIoState() == NoAsyncIoPending );
  766. DBG_REQUIRE( ( pIsapiCore = pIsapiContext->QueryIsapiCoreInterface() ) != NULL );
  767. IF_DEBUG( ISAPI_SSF_DETAILS )
  768. {
  769. DBGPRINTF(( DBG_CONTEXT,
  770. "\r\n"
  771. " HSE_REQ_DONE_WITH_SESSION[%p]: Function Entry\r\n"
  772. " <END>\r\n\r\n",
  773. pIsapiContext ));
  774. }
  775. //
  776. // If the caller wants to do STATUS_SUCCESS_AND_KEEP_CONN,
  777. // then we need to do that now.
  778. //
  779. // Note that this overrides our own determination of whether
  780. // the client can support keep-alive or not. We are trusting
  781. // the caller to have returned the right headers to make this
  782. // work with the client.
  783. //
  784. if ( pHseResult &&
  785. *pHseResult == HSE_STATUS_SUCCESS_AND_KEEP_CONN )
  786. {
  787. if ( pIsapiContext->QueryClientKeepConn() )
  788. {
  789. pIsapiContext->SetKeepConn( TRUE );
  790. pIsapiCore->SetConnectionClose( !pIsapiContext->QueryKeepConn() );
  791. }
  792. }
  793. //
  794. // We'll just release the reference on IsapiContext.
  795. // Its destructor will do the rest.
  796. //
  797. pIsapiContext->DereferenceIsapiContext();
  798. pIsapiContext = NULL;
  799. return NO_ERROR;
  800. }
  801. HRESULT
  802. SSFGetCertInfoEx(
  803. ISAPI_CONTEXT * pIsapiContext,
  804. CERT_CONTEXT_EX * pCertContext
  805. )
  806. /*++
  807. Routine Description:
  808. Returns certificate information about the client associated
  809. with this request.
  810. Arguments:
  811. pIsapiContext - The ISAPI_CONTEXT associated with this command.
  812. pCertContext - Upon return, contains info about the client cert.
  813. Return Value:
  814. HRESULT
  815. --*/
  816. {
  817. IIsapiCore * pIsapiCore;
  818. HRESULT hr;
  819. DBG_ASSERT( pIsapiContext );
  820. DBG_ASSERT( pIsapiContext->CheckSignature() );
  821. IF_DEBUG( ISAPI_SSF_DETAILS )
  822. {
  823. DBGPRINTF(( DBG_CONTEXT,
  824. "\r\n"
  825. " HSE_REQ_GET_CERT_INFO_EX[%p]: Function Entry\r\n"
  826. " <END>\r\n\r\n",
  827. pIsapiContext ));
  828. }
  829. pIsapiCore = pIsapiContext->QueryIsapiCoreInterface();
  830. if ( pIsapiCore == NULL )
  831. {
  832. IF_DEBUG( ISAPI_ERROR_RETURNS )
  833. {
  834. DBGPRINTF(( DBG_CONTEXT,
  835. "\r\n"
  836. " HSE_REQ_GET_CERT_INFO_EX[%p]: Failed to get interface to server core\r\n"
  837. " <END>\r\n\r\n",
  838. pIsapiContext ));
  839. }
  840. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  841. }
  842. //
  843. // Validate parameters
  844. //
  845. if ( pCertContext == NULL )
  846. {
  847. IF_DEBUG( ISAPI_ERROR_RETURNS )
  848. {
  849. DBGPRINTF(( DBG_CONTEXT,
  850. "\r\n"
  851. " HSE_REQ_GET_CERT_INFO_EX[%p]: Parameter validation failure\r\n"
  852. " CertContext Ptr: NULL\r\n"
  853. " <END>\r\n\r\n",
  854. pIsapiContext ));
  855. }
  856. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  857. }
  858. hr = pIsapiCore->GetCertificateInfoEx(
  859. pCertContext->cbAllocated,
  860. &( pCertContext->CertContext.dwCertEncodingType ),
  861. pCertContext->CertContext.pbCertEncoded,
  862. &( pCertContext->CertContext.cbCertEncoded ),
  863. &( pCertContext->dwCertificateFlags ) );
  864. if ( FAILED( hr ) )
  865. {
  866. IF_DEBUG( ISAPI_ERROR_RETURNS )
  867. {
  868. DBGPRINTF(( DBG_CONTEXT,
  869. "\r\n"
  870. " HSE_REQ_GET_CERT_INFO_EX[%p]: Failed\r\n"
  871. " Error: 0x%08x\r\n"
  872. " <END>\r\n\r\n",
  873. pIsapiContext,
  874. hr ));
  875. }
  876. return hr;
  877. }
  878. return hr;
  879. }
  880. HRESULT
  881. SSFIoCompletion(
  882. ISAPI_CONTEXT * pIsapiContext,
  883. PFN_HSE_IO_COMPLETION pCompletionRoutine,
  884. LPVOID pHseIoContext
  885. )
  886. /*++
  887. Routine Description:
  888. Establishes the I/O completion routine and user-defined context
  889. to be used for asynchronous operations associated with this
  890. request.
  891. Arguments:
  892. pIsapiContext - The ISAPI_CONTEXT associated with this command.
  893. pCompletionRoutine - The function to call upon I/O completion
  894. pHseIoContext - The user-defined context to be passed to the
  895. completion routine.
  896. Return Value:
  897. HRESULT
  898. --*/
  899. {
  900. DBG_ASSERT( pIsapiContext );
  901. DBG_ASSERT( pIsapiContext->CheckSignature() );
  902. IF_DEBUG( ISAPI_SSF_DETAILS )
  903. {
  904. DBGPRINTF(( DBG_CONTEXT,
  905. "\r\n"
  906. " HSE_REQ_IO_COMPLETION[%p]: Function Entry\r\n"
  907. " Completion Routine: %p\r\n"
  908. " Context: %p\r\n"
  909. " <END>\r\n\r\n",
  910. pIsapiContext,
  911. pCompletionRoutine,
  912. pHseIoContext ));
  913. }
  914. //
  915. // Validate parameters
  916. //
  917. if ( pCompletionRoutine == NULL )
  918. {
  919. IF_DEBUG( ISAPI_ERROR_RETURNS )
  920. {
  921. DBGPRINTF(( DBG_CONTEXT,
  922. "\r\n"
  923. " HSE_REQ_IO_COMPLETION[%p]: Parameter validation failure\r\n"
  924. " Completion Routine: NULL\r\n"
  925. " <END>\r\n\r\n",
  926. pIsapiContext ));
  927. }
  928. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  929. }
  930. pIsapiContext->SetPfnIoCompletion( pCompletionRoutine );
  931. pIsapiContext->SetExtensionContext( pHseIoContext );
  932. return NO_ERROR;
  933. }
  934. HRESULT
  935. SSFAsyncReadClient(
  936. ISAPI_CONTEXT * pIsapiContext,
  937. LPVOID pBuffer,
  938. LPDWORD pcbBuffer
  939. )
  940. /*++
  941. Routine Description:
  942. Queues an asynchronous read of data from the client.
  943. Arguments:
  944. pIsapiContext - The ISAPI_CONTEXT associated with this command.
  945. pBuffer - Buffer to be filled with read data.
  946. pcbBuffer - The size of pBuffer
  947. Return Value:
  948. HRESULT
  949. --*/
  950. {
  951. IIsapiCore * pIsapiCore;
  952. DWORD cbBuffer;
  953. HRESULT hr = NOERROR;
  954. DBG_ASSERT( pIsapiContext );
  955. DBG_ASSERT( pIsapiContext->CheckSignature() );
  956. IF_DEBUG( ISAPI_SSF_DETAILS )
  957. {
  958. DBGPRINTF(( DBG_CONTEXT,
  959. "\r\n"
  960. " HSE_REQ_ASYNC_READ_CLIENT[%p]: Function Entry\r\n"
  961. " Bytes to Read: %d\r\n"
  962. " <END>\r\n\r\n",
  963. pIsapiContext,
  964. pcbBuffer ? *pcbBuffer : 0 ));
  965. }
  966. pIsapiCore = pIsapiContext->QueryIsapiCoreInterface();
  967. if ( pIsapiCore == NULL )
  968. {
  969. IF_DEBUG( ISAPI_ERROR_RETURNS )
  970. {
  971. DBGPRINTF(( DBG_CONTEXT,
  972. "\r\n"
  973. " HSE_REQ_ASYNC_READ_CLIENT[%p]: Failed to get interface to server core\r\n"
  974. " <END>\r\n\r\n",
  975. pIsapiContext ));
  976. }
  977. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  978. }
  979. //
  980. // Validate parameters
  981. //
  982. if ( pIsapiContext->QueryPfnIoCompletion() == NULL ||
  983. pBuffer == NULL ||
  984. pcbBuffer == NULL ||
  985. *pcbBuffer == 0 )
  986. {
  987. IF_DEBUG( ISAPI_ERROR_RETURNS )
  988. {
  989. DBGPRINTF(( DBG_CONTEXT,
  990. "\r\n"
  991. " HSE_REQ_ASYNC_READ_CLIENT[%p]: Parameter validation failure\r\n"
  992. " Completion Routine: %p\r\n"
  993. " Buffer Ptr: %p\r\n"
  994. " Buffer Size Ptr: %p\r\n"
  995. " Buffer Size: %d\r\n"
  996. " <END>\r\n\r\n",
  997. pIsapiContext,
  998. pIsapiContext->QueryPfnIoCompletion(),
  999. pBuffer,
  1000. pcbBuffer,
  1001. pcbBuffer ? *pcbBuffer : 0 ));
  1002. }
  1003. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  1004. }
  1005. //
  1006. // Do the async ReadClient call
  1007. //
  1008. if ( pIsapiContext->TryInitAsyncIo( AsyncReadPending ) == FALSE )
  1009. {
  1010. IF_DEBUG( ISAPI_ERROR_RETURNS )
  1011. {
  1012. DBGPRINTF(( DBG_CONTEXT,
  1013. "\r\n"
  1014. " HSE_REQ_ASYNC_READ_CLIENT[%p]: Failed\r\n"
  1015. " Another async operation is already pending\r\n"
  1016. " <END>\r\n\r\n",
  1017. pIsapiContext ));
  1018. }
  1019. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  1020. }
  1021. //
  1022. // Since we're never actually reading any data in the async
  1023. // case, we want to prevent pIsapiCore->ReadClient() from
  1024. // modifying the buffer size we report back to the caller,
  1025. // so we'll use a local for cbBuffer.
  1026. //
  1027. cbBuffer = *pcbBuffer;
  1028. //
  1029. // If this call will be going OOP, save a pointer to the
  1030. // read buffer so that the core can fill it when the
  1031. // operation completes.
  1032. //
  1033. if ( pIsapiContext->QueryIsOop() )
  1034. {
  1035. DBG_ASSERT( pIsapiContext->QueryAsyncIoBuffer() == NULL );
  1036. DBG_ASSERT( pIsapiContext->QueryLastAsyncIo() == 0 );
  1037. pIsapiContext->SetAsyncIoBuffer( pBuffer );
  1038. pIsapiContext->SetLastAsyncIo( cbBuffer );
  1039. }
  1040. hr = pIsapiCore->ReadClient(
  1041. reinterpret_cast<DWORD64>( pIsapiContext ),
  1042. pIsapiContext->QueryIsOop() ? NULL : reinterpret_cast<unsigned char*>( pBuffer ),
  1043. pIsapiContext->QueryIsOop() ? 0 : cbBuffer,
  1044. cbBuffer,
  1045. &cbBuffer,
  1046. HSE_IO_ASYNC
  1047. );
  1048. if ( FAILED( hr ) )
  1049. {
  1050. IF_DEBUG( ISAPI_ERROR_RETURNS )
  1051. {
  1052. DBGPRINTF(( DBG_CONTEXT,
  1053. "\r\n"
  1054. " HSE_REQ_ASYNC_READ_CLIENT[%p]: Failed\r\n"
  1055. " Error: 0x%08x\r\n"
  1056. " <END>\r\n\r\n",
  1057. pIsapiContext,
  1058. hr ));
  1059. }
  1060. pIsapiContext->SetAsyncIoBuffer( NULL );
  1061. pIsapiContext->SetLastAsyncIo( 0 );
  1062. pIsapiContext->UninitAsyncIo();
  1063. }
  1064. return hr;
  1065. }
  1066. HRESULT
  1067. SSFTransmitFile(
  1068. ISAPI_CONTEXT * pIsapiContext,
  1069. HSE_TF_INFO * pTfInfo
  1070. )
  1071. /*++
  1072. Routine Description:
  1073. Transmits a file, a portion of a file, or some other data
  1074. (in the event on a NULL file handle) to the client.
  1075. Arguments:
  1076. pIsapiContext - The ISAPI_CONTEXT associated with this command.
  1077. pTfInfo - Describes the desired transmit file action.
  1078. Return Value:
  1079. HRESULT
  1080. --*/
  1081. {
  1082. IIsapiCore * pIsapiCore;
  1083. LARGE_INTEGER cbFileSize;
  1084. HRESULT hr;
  1085. DBG_ASSERT( pIsapiContext );
  1086. DBG_ASSERT( pIsapiContext->CheckSignature() );
  1087. IF_DEBUG( ISAPI_SSF_DETAILS )
  1088. {
  1089. STACK_STRA( strFilename,MAX_PATH );
  1090. DBGPRINTF(( DBG_CONTEXT,
  1091. "\r\n"
  1092. " HSE_REQ_TRANSMIT_FILE[%p]: Function Entry\r\n"
  1093. " Completion Routine: %p\r\n"
  1094. " Context: %p\r\n"
  1095. " File Handle: %p\r\n"
  1096. " Status Code: '%s'\r\n"
  1097. " Bytes To Write: %d\r\n"
  1098. " Offset: %d\r\n"
  1099. " <END>\r\n\r\n",
  1100. pIsapiContext,
  1101. pTfInfo ? pTfInfo->pfnHseIO : 0,
  1102. pTfInfo ? pTfInfo->pContext : 0,
  1103. pTfInfo ? pTfInfo->hFile : 0,
  1104. pTfInfo ? pTfInfo->pszStatusCode : 0,
  1105. pTfInfo ? pTfInfo->BytesToWrite : 0,
  1106. pTfInfo ? pTfInfo->Offset : 0 ));
  1107. IF_DEBUG( ISAPI_DUMP_BUFFERS )
  1108. {
  1109. if ( pTfInfo )
  1110. {
  1111. STACK_STRA( strHead,MAX_PATH );
  1112. STACK_STRA( strTail,MAX_PATH );
  1113. DWORD dwBytesToDump;
  1114. dwBytesToDump = pTfInfo->HeadLength;
  1115. if ( dwBytesToDump > MAX_DEBUG_DUMP )
  1116. {
  1117. dwBytesToDump = MAX_DEBUG_DUMP;
  1118. }
  1119. if ( FAILED( strHead.CopyBinary( pTfInfo->pHead, dwBytesToDump ) ) )
  1120. {
  1121. strHead.Copy( "" );
  1122. }
  1123. dwBytesToDump = pTfInfo->TailLength;
  1124. if ( dwBytesToDump > MAX_DEBUG_DUMP )
  1125. {
  1126. dwBytesToDump = MAX_DEBUG_DUMP;
  1127. }
  1128. if ( FAILED( strTail.CopyBinary( pTfInfo->pTail, dwBytesToDump ) ) )
  1129. {
  1130. strTail.Copy( "" );
  1131. }
  1132. DBGPRINTF(( DBG_CONTEXT,
  1133. "\r\n"
  1134. " HSE_REQ_TRANSMIT_FILE[%p]: Dump of up to %d bytes of head and tail data\r\n"
  1135. " Head Data:\r\n"
  1136. "%s"
  1137. " Tail Data:\r\n"
  1138. "%s"
  1139. " <END>\r\n",
  1140. pIsapiContext,
  1141. MAX_DEBUG_DUMP,
  1142. strHead.QueryStr(),
  1143. strTail.QueryStr() ));
  1144. }
  1145. }
  1146. }
  1147. pIsapiCore = pIsapiContext->QueryIsapiCoreInterface();
  1148. if ( pIsapiCore == NULL )
  1149. {
  1150. IF_DEBUG( ISAPI_ERROR_RETURNS )
  1151. {
  1152. DBGPRINTF(( DBG_CONTEXT,
  1153. "\r\n"
  1154. " HSE_REQ_TRANSMIT_FILE[%p]: Failed to get interface to server core\r\n"
  1155. " <END>\r\n\r\n",
  1156. pIsapiContext ));
  1157. }
  1158. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  1159. }
  1160. //
  1161. // Validate parameters - For TRANSMIT_FILE, this means:
  1162. //
  1163. // - We must have an ISAPI core interface to call through
  1164. // - We must have an HSE_TF_INFO structure
  1165. // - The HSE_IO_ASYNC flag must be set
  1166. // - If HeadLength is set, pHead cannot be NULL
  1167. // - If TailLength is set, pTail cannot be NULL
  1168. // - We must have either a completion routine already set
  1169. // in the ISAPI_CONTEXT, or the HSE_TF_INFO must provide
  1170. // one
  1171. // - There can be no other async operations in progress
  1172. //
  1173. if ( pTfInfo == NULL )
  1174. {
  1175. IF_DEBUG( ISAPI_ERROR_RETURNS )
  1176. {
  1177. DBGPRINTF(( DBG_CONTEXT,
  1178. "\r\n"
  1179. " HSE_REQ_TRANSMIT_FILE[%p]: Parameter validation failure\r\n"
  1180. " Transmit File Info Ptr: NULL\r\n"
  1181. " <END>\r\n\r\n",
  1182. pIsapiContext ));
  1183. }
  1184. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  1185. }
  1186. if ( ( pTfInfo->dwFlags & HSE_IO_ASYNC ) == 0 ||
  1187. pTfInfo->hFile == INVALID_HANDLE_VALUE ||
  1188. ( pTfInfo->HeadLength != 0 && pTfInfo->pHead == NULL ) ||
  1189. ( pTfInfo->TailLength != 0 && pTfInfo->pTail == NULL ) ||
  1190. ( pIsapiContext->QueryPfnIoCompletion() == NULL &&
  1191. pTfInfo->pfnHseIO == NULL ) )
  1192. {
  1193. IF_DEBUG( ISAPI_ERROR_RETURNS )
  1194. {
  1195. DBGPRINTF(( DBG_CONTEXT,
  1196. "\r\n"
  1197. " HSE_REQ_TRANSMIT_FILE[%p]: Parameter validation failure\r\n"
  1198. " %s\r\n",
  1199. " File Handle: %p\r\n"
  1200. " Head: %p\r\n"
  1201. " Head Length: %d\r\n"
  1202. " Tail: %p\r\n"
  1203. " Tail Length: %d\r\n"
  1204. " Completion Routine: %p\r\n"
  1205. " <END>\r\n\r\n",
  1206. pIsapiContext,
  1207. pTfInfo->dwFlags & HSE_IO_ASYNC ? "Async flag set" : "Async flag not set",
  1208. pTfInfo->hFile,
  1209. pTfInfo->pHead,
  1210. pTfInfo->HeadLength,
  1211. pTfInfo->pTail,
  1212. pTfInfo->TailLength,
  1213. pTfInfo->pfnHseIO ? pTfInfo->pfnHseIO : pIsapiContext->QueryPfnIoCompletion() ));
  1214. }
  1215. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  1216. }
  1217. if ( pIsapiContext->TryInitAsyncIo( AsyncWritePending ) == FALSE )
  1218. {
  1219. IF_DEBUG( ISAPI_ERROR_RETURNS )
  1220. {
  1221. DBGPRINTF(( DBG_CONTEXT,
  1222. "\r\n"
  1223. " HSE_REQ_TRANSMIT_FILE[%p]: Failed\r\n"
  1224. " Another async operation is already pending.\r\n"
  1225. " <END>\r\n\r\n",
  1226. pIsapiContext ));
  1227. }
  1228. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  1229. }
  1230. //
  1231. // We'll do some extra validation in the case where we've been
  1232. // provided a file handle.
  1233. //
  1234. // Specifically, we'll check to make sure that the offset and
  1235. // bytes-to-write are valid for the file.
  1236. //
  1237. // CODEWORK - Do we really need to do this, or can http.sys handle
  1238. // it? Also, does http.sys treat zero bytes to write
  1239. // the same as TransmitFile (ie. send the whole file?)
  1240. //
  1241. if ( pTfInfo->hFile != NULL )
  1242. {
  1243. if (!GetFileSizeEx(pTfInfo->hFile,
  1244. &cbFileSize))
  1245. {
  1246. hr = HRESULT_FROM_WIN32( GetLastError() );
  1247. goto Done;
  1248. }
  1249. if ( pTfInfo->Offset > cbFileSize.QuadPart ||
  1250. (pTfInfo->Offset > 0 && pTfInfo->Offset == cbFileSize.QuadPart ) ||
  1251. pTfInfo->Offset + pTfInfo->BytesToWrite > cbFileSize.QuadPart )
  1252. {
  1253. IF_DEBUG( ISAPI_ERROR_RETURNS )
  1254. {
  1255. DBGPRINTF(( DBG_CONTEXT,
  1256. "\r\n"
  1257. " HSE_REQ_TRANSMIT_FILE[%p]: Parameter validation failure\r\n"
  1258. " File Size: %d\r\n"
  1259. " Offset: %d\r\n"
  1260. " Bytes to Write: %d\r\n"
  1261. " <END>\r\n\r\n",
  1262. pIsapiContext,
  1263. cbFileSize.QuadPart,
  1264. pTfInfo->Offset,
  1265. pTfInfo->BytesToWrite ));
  1266. }
  1267. hr = HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  1268. goto Done;
  1269. }
  1270. }
  1271. else
  1272. {
  1273. //
  1274. // No file handle, so initialize the size to zero
  1275. //
  1276. cbFileSize.QuadPart = 0;
  1277. }
  1278. //
  1279. // If the HSE_TF_INFO includes I/O completion or context
  1280. // information, override the existing settings.
  1281. //
  1282. if ( pTfInfo->pfnHseIO )
  1283. {
  1284. pIsapiContext->SetPfnIoCompletion( pTfInfo->pfnHseIO );
  1285. }
  1286. if ( pTfInfo->pContext )
  1287. {
  1288. pIsapiContext->SetExtensionContext( pTfInfo->pContext );
  1289. }
  1290. //
  1291. // If the extension is setting HSE_IO_SEND_HEADERS, then we need
  1292. // to determine if it's sending some kind of content length. If
  1293. // it's not, then we need to set _fKeepConn to FALSE.
  1294. //
  1295. // CODEWORK
  1296. // Note that we're making a bold assumption here that if
  1297. // HSE_IO_SEND_HEADERS is set, then pHead points to a NULL
  1298. // terminated string.
  1299. //
  1300. if ( pIsapiContext->QueryClientKeepConn() &&
  1301. pTfInfo->pHead &&
  1302. ( pTfInfo->dwFlags & HSE_IO_SEND_HEADERS ) &&
  1303. !( pTfInfo->dwFlags & HSE_IO_DISCONNECT_AFTER_SEND ) )
  1304. {
  1305. if ( stristr2( (LPSTR)pTfInfo->pHead, "content-length: " ) != NULL ||
  1306. stristr2( (LPSTR)pTfInfo->pHead, "transfer-encoding: chunked" ) != NULL )
  1307. {
  1308. pIsapiContext->SetKeepConn( TRUE );
  1309. }
  1310. }
  1311. if ( pIsapiContext->QueryKeepConn() == FALSE )
  1312. {
  1313. pTfInfo->dwFlags |= HSE_IO_DISCONNECT_AFTER_SEND;
  1314. }
  1315. else
  1316. {
  1317. //
  1318. // We need to clear the HSE_IO_DISCONNECT_AFTER_SEND flag
  1319. // in the case where QueryKeepConn is TRUE.
  1320. //
  1321. pTfInfo->dwFlags &= ~HSE_IO_DISCONNECT_AFTER_SEND;
  1322. }
  1323. //
  1324. // Save the BytesToWrite part as _cbLastAsyncIo, since the size of
  1325. // pHead and pTail confuses ISAPI's that examine the cbWritten
  1326. // value on completion.
  1327. //
  1328. ULARGE_INTEGER cbToWrite;
  1329. if ( pTfInfo->BytesToWrite )
  1330. {
  1331. cbToWrite.QuadPart = pTfInfo->BytesToWrite;
  1332. }
  1333. else
  1334. {
  1335. cbToWrite.QuadPart = cbFileSize.QuadPart - pTfInfo->Offset;
  1336. }
  1337. //
  1338. // Note that ISAPI doesn't support large integer values, so the
  1339. // best we can do here is to store the low bits.
  1340. //
  1341. pIsapiContext->SetLastAsyncIo( cbToWrite.LowPart );
  1342. hr = pIsapiCore->TransmitFile(
  1343. reinterpret_cast<DWORD64>( pIsapiContext ),
  1344. reinterpret_cast<DWORD_PTR>( pTfInfo->hFile ),
  1345. pTfInfo->Offset,
  1346. cbToWrite.QuadPart,
  1347. (pTfInfo->dwFlags & HSE_IO_SEND_HEADERS) ? const_cast<LPSTR>( pTfInfo->pszStatusCode ) : NULL,
  1348. reinterpret_cast<LPBYTE>( pTfInfo->pHead ),
  1349. pTfInfo->HeadLength,
  1350. reinterpret_cast<LPBYTE>( pTfInfo->pTail ),
  1351. pTfInfo->TailLength,
  1352. pTfInfo->dwFlags
  1353. );
  1354. Done:
  1355. if ( FAILED( hr ) )
  1356. {
  1357. IF_DEBUG( ISAPI_ERROR_RETURNS )
  1358. {
  1359. DBGPRINTF(( DBG_CONTEXT,
  1360. "\r\n"
  1361. " HSE_REQ_TRANSMIT_FILE[%p]: Failed\r\n"
  1362. " Error: 0x%08x\r\n"
  1363. " <END>\r\n\r\n",
  1364. pIsapiContext,
  1365. hr ));
  1366. }
  1367. pIsapiContext->SetLastAsyncIo( 0 );
  1368. pIsapiContext->UninitAsyncIo();
  1369. }
  1370. return hr;
  1371. }
  1372. HRESULT
  1373. SSFSendRedirect(
  1374. ISAPI_CONTEXT * pIsapiContext,
  1375. LPSTR szUrl
  1376. )
  1377. /*++
  1378. Routine Description:
  1379. Sends a 302 redirect to the client associated with this request.
  1380. Arguments:
  1381. pIsapiContext - The ISAPI_CONTEXT associated with this command.
  1382. szUrl - The target URL for the redirection.
  1383. Return Value:
  1384. HRESULT
  1385. --*/
  1386. {
  1387. IIsapiCore * pIsapiCore;
  1388. HRESULT hr;
  1389. DBG_ASSERT( pIsapiContext );
  1390. DBG_ASSERT( pIsapiContext->CheckSignature() );
  1391. IF_DEBUG( ISAPI_SSF_DETAILS )
  1392. {
  1393. DBGPRINTF(( DBG_CONTEXT,
  1394. "\r\n"
  1395. " HSE_REQ_SEND_REDIRECT[%p]: Function Entry\r\n"
  1396. " URL: '%s'\r\n"
  1397. " <END>\r\n\r\n",
  1398. pIsapiContext,
  1399. szUrl ));
  1400. }
  1401. pIsapiCore = pIsapiContext->QueryIsapiCoreInterface();
  1402. if ( pIsapiCore == NULL )
  1403. {
  1404. IF_DEBUG( ISAPI_ERROR_RETURNS )
  1405. {
  1406. DBGPRINTF(( DBG_CONTEXT,
  1407. "\r\n"
  1408. " HSE_REQ_SEND_REDIRECT[%p]: Failed to get interface to server core\r\n"
  1409. " <END>\r\n\r\n",
  1410. pIsapiContext ));
  1411. }
  1412. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  1413. }
  1414. //
  1415. // Validate parameters
  1416. //
  1417. if ( pIsapiContext == NULL ||
  1418. szUrl == NULL )
  1419. {
  1420. IF_DEBUG( ISAPI_ERROR_RETURNS )
  1421. {
  1422. DBGPRINTF(( DBG_CONTEXT,
  1423. "\r\n"
  1424. " HSE_REQ_SEND_REDIRECT[%p]: Parameter validation failure\r\n"
  1425. " szUrl: '%s'\r\n"
  1426. " <END>\r\n\r\n",
  1427. pIsapiContext,
  1428. szUrl ));
  1429. }
  1430. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  1431. }
  1432. if ( pIsapiContext->QueryClientKeepConn() )
  1433. {
  1434. pIsapiContext->SetKeepConn( TRUE );
  1435. }
  1436. hr = pIsapiCore->SendRedirect(
  1437. szUrl,
  1438. !pIsapiContext->QueryKeepConn()
  1439. );
  1440. if ( FAILED( hr ) )
  1441. {
  1442. IF_DEBUG( ISAPI_ERROR_RETURNS )
  1443. {
  1444. DBGPRINTF(( DBG_CONTEXT,
  1445. "\r\n"
  1446. " HSE_REQ_SEND_REDIRECT[%p]: Failed\r\n"
  1447. " Error: 0x%08x\r\n"
  1448. " <END>\r\n\r\n",
  1449. pIsapiContext,
  1450. hr ));
  1451. }
  1452. return hr;
  1453. }
  1454. return hr;
  1455. }
  1456. HRESULT
  1457. SSFIsConnected(
  1458. ISAPI_CONTEXT * pIsapiContext,
  1459. BOOL * pfIsConnected
  1460. )
  1461. /*++
  1462. Routine Description:
  1463. Returns the connection state (connected or not connected)
  1464. of the client associated with this request.
  1465. Arguments:
  1466. pIsapiContext - The ISAPI_CONTEXT associated with this command.
  1467. pfIsConnected - TRUE upon return if the client is connected,
  1468. else FALSE.
  1469. Return Value:
  1470. HRESULT
  1471. --*/
  1472. {
  1473. IIsapiCore * pIsapiCore;
  1474. HRESULT hr;
  1475. DBG_ASSERT( pIsapiContext );
  1476. DBG_ASSERT( pIsapiContext->CheckSignature() );
  1477. IF_DEBUG( ISAPI_SSF_DETAILS )
  1478. {
  1479. DBGPRINTF(( DBG_CONTEXT,
  1480. "\r\n"
  1481. " HSE_REQ_IS_CONNECTED[%p]: Function Entry\r\n"
  1482. " <END>\r\n\r\n",
  1483. pIsapiContext ));
  1484. }
  1485. pIsapiCore = pIsapiContext->QueryIsapiCoreInterface();
  1486. if ( pIsapiCore == NULL )
  1487. {
  1488. IF_DEBUG( ISAPI_ERROR_RETURNS )
  1489. {
  1490. DBGPRINTF(( DBG_CONTEXT,
  1491. "\r\n"
  1492. " HSE_REQ_IS_CONNECTED[%p]: Failed to get interface to server core\r\n"
  1493. " <END>\r\n\r\n",
  1494. pIsapiContext ));
  1495. }
  1496. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  1497. }
  1498. //
  1499. // Validate parameters
  1500. //
  1501. if ( pfIsConnected == NULL )
  1502. {
  1503. IF_DEBUG( ISAPI_ERROR_RETURNS )
  1504. {
  1505. DBGPRINTF(( DBG_CONTEXT,
  1506. "\r\n"
  1507. " HSE_REQ_IS_CONNECTED[%p]: Parameter validation failure\r\n"
  1508. " IsConnected Ptr: NULL\r\n"
  1509. " <END>\r\n\r\n",
  1510. pIsapiContext ));
  1511. }
  1512. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  1513. }
  1514. hr = pIsapiCore->TestConnection( pfIsConnected );
  1515. if ( FAILED( hr ) )
  1516. {
  1517. IF_DEBUG( ISAPI_ERROR_RETURNS )
  1518. {
  1519. DBGPRINTF(( DBG_CONTEXT,
  1520. "\r\n"
  1521. " HSE_REQ_IS_CONNECTED[%p]: Failed\r\n"
  1522. " Error: 0x%08x\r\n"
  1523. " <END>\r\n\r\n",
  1524. pIsapiContext,
  1525. hr ));
  1526. }
  1527. return hr;
  1528. }
  1529. return hr;
  1530. }
  1531. HRESULT
  1532. SSFAppendLog(
  1533. ISAPI_CONTEXT * pIsapiContext,
  1534. LPSTR szExtraParam
  1535. )
  1536. /*++
  1537. Routine Description:
  1538. Appends the string passed to the QueryString that will be logged
  1539. Arguments:
  1540. pIsapiContext - The ISAPI_CONTEXT associated with this command.
  1541. szExtraParam - The extra parameter to be logged
  1542. Return Value:
  1543. HRESULT
  1544. --*/
  1545. {
  1546. IIsapiCore * pIsapiCore;
  1547. HRESULT hr;
  1548. DBG_ASSERT( pIsapiContext );
  1549. DBG_ASSERT( pIsapiContext->CheckSignature() );
  1550. IF_DEBUG( ISAPI_SSF_DETAILS )
  1551. {
  1552. DBGPRINTF(( DBG_CONTEXT,
  1553. "\r\n"
  1554. " HSE_REQ_APPEND_LOG_PARAMETER[%p]: Function Entry\r\n"
  1555. " Extra Param: '%s'\r\n"
  1556. " <END>\r\n\r\n",
  1557. pIsapiContext,
  1558. szExtraParam ));
  1559. }
  1560. pIsapiCore = pIsapiContext->QueryIsapiCoreInterface();
  1561. if ( pIsapiCore == NULL )
  1562. {
  1563. IF_DEBUG( ISAPI_ERROR_RETURNS )
  1564. {
  1565. DBGPRINTF(( DBG_CONTEXT,
  1566. "\r\n"
  1567. " HSE_REQ_APPEND_LOG_PARAMETER[%p]: Failed to get interface to server core\r\n"
  1568. " <END>\r\n\r\n",
  1569. pIsapiContext ));
  1570. }
  1571. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  1572. }
  1573. //
  1574. // Validate parameters
  1575. //
  1576. if ( szExtraParam == NULL )
  1577. {
  1578. IF_DEBUG( ISAPI_ERROR_RETURNS )
  1579. {
  1580. DBGPRINTF(( DBG_CONTEXT,
  1581. "\r\n"
  1582. " HSE_REQ_APPEND_LOG_PARAMETER[%p]: Parameter validation failure\r\n"
  1583. " Extra Param: NULL\r\n"
  1584. " <END>\r\n\r\n",
  1585. pIsapiContext ));
  1586. }
  1587. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  1588. }
  1589. hr = pIsapiCore->AppendLog( szExtraParam, 0 );
  1590. if ( FAILED( hr ) )
  1591. {
  1592. IF_DEBUG( ISAPI_ERROR_RETURNS )
  1593. {
  1594. DBGPRINTF(( DBG_CONTEXT,
  1595. "\r\n"
  1596. " HSE_REQ_APPEND_LOG_PARAMETER[%p]: Failed\r\n"
  1597. " Error: 0x%08x\r\n"
  1598. " <END>\r\n\r\n",
  1599. pIsapiContext,
  1600. hr ));
  1601. }
  1602. return hr;
  1603. }
  1604. return hr;
  1605. }
  1606. HRESULT
  1607. SSFExecuteUrl(
  1608. ISAPI_CONTEXT * pIsapiContext,
  1609. VOID * pOrigExecUrlInfo,
  1610. BOOL fIsUnicode
  1611. )
  1612. /*++
  1613. Routine Description:
  1614. Execute a child request
  1615. Arguments:
  1616. pIsapiContext - The ISAPI_CONTEXT associated with this command.
  1617. pOrigExecUrlInfo - Description of child request to execute
  1618. fIsUnicode - Are we passing unicode data?
  1619. Return Value:
  1620. HRESULT
  1621. --*/
  1622. {
  1623. EXEC_URL_USER_INFO UserName;
  1624. EXEC_URL_ENTITY_INFO Entity;
  1625. EXEC_URL_INFO UrlInfo;
  1626. IIsapiCore * pIsapiCore;
  1627. HRESULT hr;
  1628. DBG_ASSERT( pIsapiContext );
  1629. DBG_ASSERT( pIsapiContext->CheckSignature() );
  1630. IF_DEBUG( ISAPI_SSF_DETAILS )
  1631. {
  1632. HSE_EXEC_URL_ENTITY_INFO *pEntityInfo = NULL;
  1633. if ( fIsUnicode )
  1634. {
  1635. HSE_EXEC_UNICODE_URL_INFO *pInfo = (HSE_EXEC_UNICODE_URL_INFO *)pOrigExecUrlInfo;
  1636. HSE_EXEC_UNICODE_URL_USER_INFO *pUserInfo = NULL;
  1637. if ( pInfo )
  1638. {
  1639. pUserInfo = pInfo->pUserInfo;
  1640. pEntityInfo = pInfo->pEntity;
  1641. }
  1642. DBGPRINTF(( DBG_CONTEXT,
  1643. "\r\n"
  1644. " HSE_REQ_EXEC_UNICODE_URL[%p]: Function Entry\r\n"
  1645. " URL: '%S'\r\n"
  1646. " Method: '%s'\r\n"
  1647. " Child Headers: '%s'\r\n"
  1648. " Flags: 0x%08x (%d)\r\n"
  1649. " Impersonation Token: %p\r\n"
  1650. " Custom User Name: '%S'\r\n"
  1651. " Custom Auth Type: '%s'\r\n"
  1652. " <END>\r\n\r\n",
  1653. pIsapiContext,
  1654. pInfo ? pInfo->pszUrl : NULL,
  1655. pInfo ? pInfo->pszMethod : NULL,
  1656. pInfo ? pInfo->pszChildHeaders : NULL,
  1657. pInfo ? pInfo->dwExecUrlFlags : 0,
  1658. pInfo ? pInfo->dwExecUrlFlags : 0,
  1659. pUserInfo ? pUserInfo->hImpersonationToken : NULL,
  1660. pUserInfo ? pUserInfo->pszCustomUserName : NULL,
  1661. pUserInfo ? pUserInfo->pszCustomAuthType : NULL ));
  1662. }
  1663. else
  1664. {
  1665. HSE_EXEC_URL_INFO *pInfo = (HSE_EXEC_URL_INFO *)pOrigExecUrlInfo;
  1666. HSE_EXEC_URL_USER_INFO *pUserInfo = NULL;
  1667. if ( pInfo )
  1668. {
  1669. pUserInfo = pInfo->pUserInfo;
  1670. pEntityInfo = pInfo->pEntity;
  1671. }
  1672. DBGPRINTF(( DBG_CONTEXT,
  1673. "\r\n"
  1674. " HSE_REQ_EXEC_UNICODE_URL[%p]: Function Entry\r\n"
  1675. " URL: '%s'\r\n"
  1676. " Method: '%s'\r\n"
  1677. " Child Headers: '%s'\r\n"
  1678. " Flags: 0x%08x (%d)\r\n"
  1679. " Impersonation Token: %p\r\n"
  1680. " Custom User Name: '%s'\r\n"
  1681. " Custom Auth Type: '%s'\r\n"
  1682. " <END>\r\n\r\n",
  1683. pIsapiContext,
  1684. pInfo ? pInfo->pszUrl : NULL,
  1685. pInfo ? pInfo->pszMethod : NULL,
  1686. pInfo ? pInfo->pszChildHeaders : NULL,
  1687. pInfo ? pInfo->dwExecUrlFlags : 0,
  1688. pInfo ? pInfo->dwExecUrlFlags : 0,
  1689. pUserInfo ? pUserInfo->hImpersonationToken : NULL,
  1690. pUserInfo ? pUserInfo->pszCustomUserName : NULL,
  1691. pUserInfo ? pUserInfo->pszCustomAuthType : NULL ));
  1692. }
  1693. IF_DEBUG( ISAPI_DUMP_BUFFERS )
  1694. {
  1695. if ( pEntityInfo )
  1696. {
  1697. STACK_STRA( strBufferDump,512 );
  1698. DWORD dwBytesToDump = pEntityInfo->cbAvailable;
  1699. if ( dwBytesToDump > MAX_DEBUG_DUMP )
  1700. {
  1701. dwBytesToDump = MAX_DEBUG_DUMP;
  1702. }
  1703. if ( FAILED( strBufferDump.CopyBinary( pEntityInfo->lpbData, dwBytesToDump ) ) )
  1704. {
  1705. strBufferDump.Copy( "" );
  1706. }
  1707. DBGPRINTF(( DBG_CONTEXT,
  1708. "\r\n"
  1709. " HSE_REQ_EXEC_URL[%p]: Dump of up to %d bytes of entity\r\n"
  1710. "%s"
  1711. " <END>\r\n\r\n",
  1712. pIsapiContext,
  1713. MAX_DEBUG_DUMP,
  1714. strBufferDump.QueryStr() ));
  1715. }
  1716. }
  1717. }
  1718. pIsapiCore = pIsapiContext->QueryIsapiCoreInterface();
  1719. if ( pIsapiCore == NULL )
  1720. {
  1721. IF_DEBUG( ISAPI_ERROR_RETURNS )
  1722. {
  1723. DBGPRINTF(( DBG_CONTEXT,
  1724. "\r\n"
  1725. " HSE_REQ_EXEC_URL[%p]: Failed to get interface to server core\r\n"
  1726. " <END>\r\n\r\n",
  1727. pIsapiContext ));
  1728. }
  1729. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  1730. }
  1731. if ( pOrigExecUrlInfo == NULL )
  1732. {
  1733. IF_DEBUG( ISAPI_ERROR_RETURNS )
  1734. {
  1735. DBGPRINTF(( DBG_CONTEXT,
  1736. "\r\n"
  1737. " HSE_REQ_EXEC_URL[%p]: Parameter validation failure\r\n"
  1738. " ExecUrl Info: NULL\r\n"
  1739. " <END>\r\n\r\n",
  1740. pIsapiContext ));
  1741. }
  1742. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  1743. }
  1744. //
  1745. // This is an async call, make sure a completion routine is set
  1746. //
  1747. if ( pIsapiContext->QueryPfnIoCompletion() == NULL )
  1748. {
  1749. IF_DEBUG( ISAPI_ERROR_RETURNS )
  1750. {
  1751. DBGPRINTF(( DBG_CONTEXT,
  1752. "\r\n"
  1753. " HSE_REQ_EXEC_URL[%p]: Failed\r\n"
  1754. " No I/O completion has been set: NULL\r\n"
  1755. " <END>\r\n\r\n",
  1756. pIsapiContext ));
  1757. }
  1758. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  1759. }
  1760. if ( pIsapiContext->TryInitAsyncIo( AsyncExecPending ) == FALSE )
  1761. {
  1762. IF_DEBUG( ISAPI_ERROR_RETURNS )
  1763. {
  1764. DBGPRINTF(( DBG_CONTEXT,
  1765. "\r\n"
  1766. " HSE_REQ_EXEC_URL[%p]: Failed\r\n"
  1767. " An async operation is already pending: NULL\r\n"
  1768. " <END>\r\n\r\n",
  1769. pIsapiContext ));
  1770. }
  1771. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  1772. }
  1773. //
  1774. // If any of the optional parameters are not NULL, then ensure they are
  1775. // not empty. Also, copy parameters to the marshallable structure
  1776. //
  1777. // Note that any failures from here on down need to goto Done so
  1778. // that we properly uninitialize async IO.
  1779. //
  1780. if (fIsUnicode)
  1781. {
  1782. HSE_EXEC_UNICODE_URL_INFO *pExecUnicodeUrlInfo =
  1783. (HSE_EXEC_UNICODE_URL_INFO *)pOrigExecUrlInfo;
  1784. if ( pExecUnicodeUrlInfo->pszUrl != NULL )
  1785. {
  1786. if ( pExecUnicodeUrlInfo->pszUrl[ 0 ] == L'\0' )
  1787. {
  1788. IF_DEBUG( ISAPI_ERROR_RETURNS )
  1789. {
  1790. DBGPRINTF(( DBG_CONTEXT,
  1791. "\r\n"
  1792. " HSE_REQ_EXEC_UNICODE_URL[%p]: Parameter validation failure\r\n"
  1793. " URL is an empty string.\r\n"
  1794. " <END>\r\n\r\n",
  1795. pIsapiContext ));
  1796. }
  1797. hr = HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  1798. goto Done;
  1799. }
  1800. UrlInfo.fIsUrlUnicode = TRUE;
  1801. UrlInfo.pszUrl = (BYTE *)pExecUnicodeUrlInfo->pszUrl;
  1802. UrlInfo.cbUrl = (DWORD)(wcslen(pExecUnicodeUrlInfo->pszUrl) + 1)*sizeof(WCHAR);
  1803. }
  1804. else
  1805. {
  1806. UrlInfo.pszUrl = NULL;
  1807. UrlInfo.cbUrl = 0;
  1808. }
  1809. if ( pExecUnicodeUrlInfo->pszMethod != NULL )
  1810. {
  1811. if ( pExecUnicodeUrlInfo->pszMethod[ 0 ] == '\0' )
  1812. {
  1813. IF_DEBUG( ISAPI_ERROR_RETURNS )
  1814. {
  1815. DBGPRINTF(( DBG_CONTEXT,
  1816. "\r\n"
  1817. " HSE_REQ_EXEC_UNICODE_URL[%p]: Parameter validation failure\r\n"
  1818. " Method is an empty string\r\n"
  1819. " <END>\r\n\r\n",
  1820. pIsapiContext ));
  1821. }
  1822. hr = HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  1823. goto Done;
  1824. }
  1825. }
  1826. UrlInfo.pszMethod = pExecUnicodeUrlInfo->pszMethod;
  1827. if ( pExecUnicodeUrlInfo->pszChildHeaders != NULL )
  1828. {
  1829. if ( pExecUnicodeUrlInfo->pszChildHeaders[ 0 ] == '\0' )
  1830. {
  1831. IF_DEBUG( ISAPI_ERROR_RETURNS )
  1832. {
  1833. DBGPRINTF(( DBG_CONTEXT,
  1834. "\r\n"
  1835. " HSE_REQ_EXEC_UNICODE_URL[%p]: Parameter validation failure\r\n"
  1836. " ChildHeaders is an empty string\r\n"
  1837. " <END>\r\n\r\n",
  1838. pIsapiContext ));
  1839. }
  1840. hr = HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  1841. goto Done;
  1842. }
  1843. }
  1844. UrlInfo.pszChildHeaders = pExecUnicodeUrlInfo->pszChildHeaders;
  1845. if ( pExecUnicodeUrlInfo->pUserInfo != NULL )
  1846. {
  1847. if ( pExecUnicodeUrlInfo->pUserInfo->pszCustomUserName == NULL )
  1848. {
  1849. IF_DEBUG( ISAPI_ERROR_RETURNS )
  1850. {
  1851. DBGPRINTF(( DBG_CONTEXT,
  1852. "\r\n"
  1853. " HSE_REQ_EXEC_UNICODE_URL[%p]: Parameter validation failure\r\n"
  1854. " Custom User Name: NULL\r\n"
  1855. " <END>\r\n\r\n",
  1856. pIsapiContext ));
  1857. }
  1858. hr = HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  1859. goto Done;
  1860. }
  1861. if ( pExecUnicodeUrlInfo->pUserInfo->pszCustomAuthType == NULL )
  1862. {
  1863. IF_DEBUG( ISAPI_ERROR_RETURNS )
  1864. {
  1865. DBGPRINTF(( DBG_CONTEXT,
  1866. "\r\n"
  1867. " HSE_REQ_EXEC_UNICODE_URL[%p]: Parameter validation failure\r\n"
  1868. " Custom Auth Type: NULL\r\n"
  1869. " <END>\r\n\r\n",
  1870. pIsapiContext ));
  1871. }
  1872. hr = HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  1873. goto Done;
  1874. }
  1875. UserName.fIsUserNameUnicode = TRUE;
  1876. UserName.pszUserName = (BYTE *)pExecUnicodeUrlInfo->pUserInfo->pszCustomUserName;
  1877. UserName.cbUserName = (DWORD)(wcslen(pExecUnicodeUrlInfo->pUserInfo->pszCustomUserName) + 1)*sizeof(WCHAR);
  1878. UserName.pszAuthType = pExecUnicodeUrlInfo->pUserInfo->pszCustomAuthType;
  1879. UserName.hImpersonationToken = (DWORD_PTR)pExecUnicodeUrlInfo->pUserInfo->hImpersonationToken;
  1880. UrlInfo.pUserInfo = &UserName;
  1881. }
  1882. else
  1883. {
  1884. UrlInfo.pUserInfo = NULL;
  1885. }
  1886. //
  1887. // If we are being told that there is available entity, ensure
  1888. // that the buffer is not NULL
  1889. //
  1890. if ( pExecUnicodeUrlInfo->pEntity != NULL )
  1891. {
  1892. if ( pExecUnicodeUrlInfo->pEntity->cbAvailable != 0 &&
  1893. pExecUnicodeUrlInfo->pEntity->lpbData == NULL )
  1894. {
  1895. IF_DEBUG( ISAPI_ERROR_RETURNS )
  1896. {
  1897. DBGPRINTF(( DBG_CONTEXT,
  1898. "\r\n"
  1899. " HSE_REQ_EXEC_UNICODE_URL[%p]: Parameter validation failure\r\n"
  1900. " Available Entity bytes: %d\r\n"
  1901. " Available Entity Ptr: %p\r\n"
  1902. " <END>\r\n\r\n",
  1903. pIsapiContext,
  1904. pExecUnicodeUrlInfo->pEntity->cbAvailable,
  1905. pExecUnicodeUrlInfo->pEntity->lpbData ));
  1906. }
  1907. hr = HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  1908. goto Done;
  1909. }
  1910. Entity.cbAvailable = pExecUnicodeUrlInfo->pEntity->cbAvailable;
  1911. Entity.lpbData = (BYTE *)pExecUnicodeUrlInfo->pEntity->lpbData;
  1912. }
  1913. else
  1914. {
  1915. //
  1916. // If no entity body was set for this child execute, then
  1917. // we should duplicate the original entity body. This means
  1918. // we will need to bring over the preloaded entity for the
  1919. // ISAPI which calls this routine.
  1920. //
  1921. Entity.cbAvailable = pIsapiContext->QueryECB()->cbAvailable;
  1922. Entity.lpbData = pIsapiContext->QueryECB()->lpbData;
  1923. }
  1924. UrlInfo.pEntity = &Entity;
  1925. UrlInfo.dwExecUrlFlags = pExecUnicodeUrlInfo->dwExecUrlFlags;
  1926. }
  1927. else
  1928. {
  1929. HSE_EXEC_URL_INFO *pExecAnsiUrlInfo =
  1930. (HSE_EXEC_URL_INFO *)pOrigExecUrlInfo;
  1931. if ( pExecAnsiUrlInfo->pszUrl != NULL )
  1932. {
  1933. if ( pExecAnsiUrlInfo->pszUrl[ 0 ] == '\0' )
  1934. {
  1935. IF_DEBUG( ISAPI_ERROR_RETURNS )
  1936. {
  1937. DBGPRINTF(( DBG_CONTEXT,
  1938. "\r\n"
  1939. " HSE_REQ_EXEC_URL[%p]: Parameter validation failure\r\n"
  1940. " URL is an empty string\r\n"
  1941. " <END>\r\n\r\n",
  1942. pIsapiContext ));
  1943. }
  1944. hr = HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  1945. goto Done;
  1946. }
  1947. UrlInfo.fIsUrlUnicode = FALSE;
  1948. UrlInfo.pszUrl = (BYTE *)pExecAnsiUrlInfo->pszUrl;
  1949. UrlInfo.cbUrl = (DWORD)strlen(pExecAnsiUrlInfo->pszUrl) + 1;
  1950. }
  1951. else
  1952. {
  1953. UrlInfo.pszUrl = NULL;
  1954. UrlInfo.cbUrl = 0;
  1955. }
  1956. if ( pExecAnsiUrlInfo->pszMethod != NULL )
  1957. {
  1958. if ( pExecAnsiUrlInfo->pszMethod[ 0 ] == '\0' )
  1959. {
  1960. IF_DEBUG( ISAPI_ERROR_RETURNS )
  1961. {
  1962. DBGPRINTF(( DBG_CONTEXT,
  1963. "\r\n"
  1964. " HSE_REQ_EXEC_URL[%p]: Parameter validation failure\r\n"
  1965. " Method is an empty string\r\n"
  1966. " <END>\r\n\r\n",
  1967. pIsapiContext ));
  1968. }
  1969. hr = HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  1970. goto Done;
  1971. }
  1972. }
  1973. UrlInfo.pszMethod = pExecAnsiUrlInfo->pszMethod;
  1974. if ( pExecAnsiUrlInfo->pszChildHeaders != NULL )
  1975. {
  1976. if ( pExecAnsiUrlInfo->pszChildHeaders[ 0 ] == '\0' )
  1977. {
  1978. IF_DEBUG( ISAPI_ERROR_RETURNS )
  1979. {
  1980. DBGPRINTF(( DBG_CONTEXT,
  1981. "\r\n"
  1982. " HSE_REQ_EXEC_URL[%p]: Parameter validation failure\r\n"
  1983. " ChildHeaders is an empty string\r\n"
  1984. " <END>\r\n\r\n",
  1985. pIsapiContext ));
  1986. }
  1987. hr = HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  1988. goto Done;
  1989. }
  1990. }
  1991. UrlInfo.pszChildHeaders = pExecAnsiUrlInfo->pszChildHeaders;
  1992. if ( pExecAnsiUrlInfo->pUserInfo != NULL )
  1993. {
  1994. if ( pExecAnsiUrlInfo->pUserInfo->pszCustomUserName == NULL )
  1995. {
  1996. IF_DEBUG( ISAPI_ERROR_RETURNS )
  1997. {
  1998. DBGPRINTF(( DBG_CONTEXT,
  1999. "\r\n"
  2000. " HSE_REQ_EXEC_URL[%p]: Parameter validation failure\r\n"
  2001. " Custom User Name: NULL\r\n"
  2002. " <END>\r\n\r\n",
  2003. pIsapiContext ));
  2004. }
  2005. hr = HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  2006. goto Done;
  2007. }
  2008. if ( pExecAnsiUrlInfo->pUserInfo->pszCustomAuthType == NULL )
  2009. {
  2010. IF_DEBUG( ISAPI_ERROR_RETURNS )
  2011. {
  2012. DBGPRINTF(( DBG_CONTEXT,
  2013. "\r\n"
  2014. " HSE_REQ_EXEC_URL[%p]: Parameter validation failure\r\n"
  2015. " Custom Auth Type: NULL\r\n"
  2016. " <END>\r\n\r\n",
  2017. pIsapiContext ));
  2018. }
  2019. hr = HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  2020. goto Done;
  2021. }
  2022. UserName.fIsUserNameUnicode = FALSE;
  2023. UserName.pszUserName = (BYTE *)pExecAnsiUrlInfo->pUserInfo->pszCustomUserName;
  2024. UserName.cbUserName = (DWORD)strlen(pExecAnsiUrlInfo->pUserInfo->pszCustomUserName) + 1;
  2025. UserName.pszAuthType = pExecAnsiUrlInfo->pUserInfo->pszCustomAuthType;
  2026. UserName.hImpersonationToken = (DWORD_PTR)pExecAnsiUrlInfo->pUserInfo->hImpersonationToken;
  2027. UrlInfo.pUserInfo = &UserName;
  2028. }
  2029. else
  2030. {
  2031. UrlInfo.pUserInfo = NULL;
  2032. }
  2033. //
  2034. // If we are being told that there is available entity, ensure
  2035. // that the buffer is not NULL
  2036. //
  2037. if ( pExecAnsiUrlInfo->pEntity != NULL )
  2038. {
  2039. if ( pExecAnsiUrlInfo->pEntity->cbAvailable != 0 &&
  2040. pExecAnsiUrlInfo->pEntity->lpbData == NULL )
  2041. {
  2042. IF_DEBUG( ISAPI_ERROR_RETURNS )
  2043. {
  2044. DBGPRINTF(( DBG_CONTEXT,
  2045. "\r\n"
  2046. " HSE_REQ_EXEC_URL[%p]: Parameter validation failure\r\n"
  2047. " Available Entity Bytes: %d\r\n"
  2048. " Available Entity Ptr: %p\r\n"
  2049. " <END>\r\n\r\n",
  2050. pIsapiContext,
  2051. pExecAnsiUrlInfo->pEntity->cbAvailable,
  2052. pExecAnsiUrlInfo->pEntity->lpbData ));
  2053. }
  2054. hr = HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  2055. goto Done;
  2056. }
  2057. Entity.cbAvailable = pExecAnsiUrlInfo->pEntity->cbAvailable;
  2058. Entity.lpbData = (BYTE *)pExecAnsiUrlInfo->pEntity->lpbData;
  2059. }
  2060. else
  2061. {
  2062. //
  2063. // If no entity body was set for this child execute, then
  2064. // we should duplicate the original entity body. This means
  2065. // we will need to bring over the preloaded entity for the
  2066. // ISAPI which calls this routine.
  2067. //
  2068. Entity.cbAvailable = pIsapiContext->QueryECB()->cbAvailable;
  2069. Entity.lpbData = pIsapiContext->QueryECB()->lpbData;
  2070. }
  2071. UrlInfo.pEntity = &Entity;
  2072. UrlInfo.dwExecUrlFlags = pExecAnsiUrlInfo->dwExecUrlFlags;
  2073. }
  2074. //
  2075. // All the heavy lifting is in W3CORE.DLL
  2076. //
  2077. hr = pIsapiCore->ExecuteUrl(
  2078. reinterpret_cast<DWORD64>( pIsapiContext ),
  2079. &UrlInfo
  2080. );
  2081. Done:
  2082. if ( FAILED( hr ) )
  2083. {
  2084. IF_DEBUG( ISAPI_ERROR_RETURNS )
  2085. {
  2086. DBGPRINTF(( DBG_CONTEXT,
  2087. "\r\n"
  2088. " HSE_REQ_EXEC_URL[%p]: Failed\r\n"
  2089. " Error: 0x%08x\r\n"
  2090. " <END>\r\n\r\n",
  2091. pIsapiContext,
  2092. hr ));
  2093. }
  2094. pIsapiContext->UninitAsyncIo();
  2095. }
  2096. return hr;
  2097. }
  2098. HRESULT
  2099. SSFGetExecuteUrlStatus(
  2100. ISAPI_CONTEXT * pIsapiContext,
  2101. HSE_EXEC_URL_STATUS* pExecUrlStatus
  2102. )
  2103. /*++
  2104. Routine Description:
  2105. Get status of last child execute
  2106. Arguments:
  2107. pIsapiContext - The ISAPI_CONTEXT associated with this command.
  2108. pExecUrlStatus - Filled with status
  2109. Return Value:
  2110. HRESULT
  2111. --*/
  2112. {
  2113. IIsapiCore * pIsapiCore;
  2114. HRESULT hr;
  2115. DBG_ASSERT( pIsapiContext );
  2116. DBG_ASSERT( pIsapiContext->CheckSignature() );
  2117. IF_DEBUG( ISAPI_SSF_DETAILS )
  2118. {
  2119. DBGPRINTF(( DBG_CONTEXT,
  2120. "\r\n"
  2121. " HSE_REQ_GET_EXEC_URL_STATUS[%p]: Function Entry\r\n"
  2122. " <END>\r\n\r\n",
  2123. pIsapiContext ));
  2124. }
  2125. pIsapiCore = pIsapiContext->QueryIsapiCoreInterface();
  2126. if ( pIsapiCore == NULL )
  2127. {
  2128. IF_DEBUG( ISAPI_ERROR_RETURNS )
  2129. {
  2130. DBGPRINTF(( DBG_CONTEXT,
  2131. "\r\n"
  2132. " HSE_REQ_GET_EXEC_URL_STATUS[%p]: Failed to get interface to server core\r\n"
  2133. " <END>\r\n\r\n",
  2134. pIsapiContext ));
  2135. }
  2136. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  2137. }
  2138. if ( pExecUrlStatus == NULL )
  2139. {
  2140. IF_DEBUG( ISAPI_ERROR_RETURNS )
  2141. {
  2142. DBGPRINTF(( DBG_CONTEXT,
  2143. "\r\n"
  2144. " HSE_REQ_GET_EXEC_URL_STATUS[%p]: Parameter validation failure\r\n"
  2145. " EXEC_URL Status Ptr: NULL\r\n"
  2146. " <END>\r\n\r\n",
  2147. pIsapiContext ));
  2148. }
  2149. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  2150. }
  2151. hr = pIsapiCore->GetExecuteUrlStatus(
  2152. &(pExecUrlStatus->uHttpStatusCode),
  2153. &(pExecUrlStatus->uHttpSubStatus),
  2154. &(pExecUrlStatus->dwWin32Error)
  2155. );
  2156. if ( FAILED( hr ) )
  2157. {
  2158. IF_DEBUG( ISAPI_ERROR_RETURNS )
  2159. {
  2160. DBGPRINTF(( DBG_CONTEXT,
  2161. "\r\n"
  2162. " HSE_REQ_GET_EXEC_URL_STATUS[%p]: Failed\r\n"
  2163. " Error: 0x%08x\r\n"
  2164. " <END>\r\n\r\n",
  2165. pIsapiContext,
  2166. hr ));
  2167. }
  2168. return hr;
  2169. }
  2170. return hr;
  2171. }
  2172. HRESULT
  2173. SSFSendCustomError(
  2174. ISAPI_CONTEXT * pIsapiContext,
  2175. HSE_CUSTOM_ERROR_INFO * pCustomErrorInfo
  2176. )
  2177. /*++
  2178. Routine Description:
  2179. Send custom error to client
  2180. Arguments:
  2181. pIsapiContext - The ISAPI_CONTEXT associated with this command.
  2182. pCustomErrorInfo - Describes the custom error to send
  2183. Return Value:
  2184. HRESULT
  2185. --*/
  2186. {
  2187. IIsapiCore * pIsapiCore;
  2188. HRESULT hr = NOERROR;
  2189. DBG_ASSERT( pIsapiContext );
  2190. DBG_ASSERT( pIsapiContext->CheckSignature() );
  2191. IF_DEBUG( ISAPI_SSF_DETAILS )
  2192. {
  2193. DBGPRINTF(( DBG_CONTEXT,
  2194. "\r\n"
  2195. " HSE_REQ_SEND_CUSTOM_ERROR[%p]: Function Entry\r\n"
  2196. " Status: '%s'\r\n"
  2197. " SubError Code: %d\r\n"
  2198. " <END>\r\n\r\n",
  2199. pIsapiContext,
  2200. pCustomErrorInfo ? pCustomErrorInfo->pszStatus : NULL,
  2201. pCustomErrorInfo ? pCustomErrorInfo->uHttpSubError : 0 ));
  2202. }
  2203. pIsapiCore = pIsapiContext->QueryIsapiCoreInterface();
  2204. if ( pIsapiCore == NULL )
  2205. {
  2206. IF_DEBUG( ISAPI_ERROR_RETURNS )
  2207. {
  2208. DBGPRINTF(( DBG_CONTEXT,
  2209. "\r\n"
  2210. " HSE_REQ_SEND_CUSTOM_ERROR[%p]: Failed to get interface to server core\r\n"
  2211. " <END>\r\n\r\n",
  2212. pIsapiContext ));
  2213. }
  2214. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  2215. }
  2216. if ( pCustomErrorInfo == NULL )
  2217. {
  2218. IF_DEBUG( ISAPI_ERROR_RETURNS )
  2219. {
  2220. DBGPRINTF(( DBG_CONTEXT,
  2221. "\r\n"
  2222. " HSE_REQ_SEND_CUSTOM_ERROR[%p]: Parameter validation failure\r\n"
  2223. " Custom Error Info Ptr: NULL\r\n"
  2224. " <END>\r\n\r\n",
  2225. pIsapiContext ));
  2226. }
  2227. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  2228. }
  2229. //
  2230. // Ensure status is not empty
  2231. //
  2232. if ( pCustomErrorInfo->pszStatus != NULL )
  2233. {
  2234. if ( pCustomErrorInfo->pszStatus[ 0 ] == '\0' )
  2235. {
  2236. IF_DEBUG( ISAPI_ERROR_RETURNS )
  2237. {
  2238. DBGPRINTF(( DBG_CONTEXT,
  2239. "\r\n"
  2240. " HSE_REQ_SEND_CUSTOM_ERROR[%p]: Parameter validation failure\r\n"
  2241. " Status is an empty string\r\n"
  2242. " <END>\r\n\r\n",
  2243. pIsapiContext ));
  2244. }
  2245. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  2246. }
  2247. }
  2248. //
  2249. // If this is an async call, then make sure a completion routine is set
  2250. //
  2251. if ( pCustomErrorInfo->fAsync )
  2252. {
  2253. if ( pIsapiContext->TryInitAsyncIo( AsyncExecPending ) == FALSE )
  2254. {
  2255. IF_DEBUG( ISAPI_ERROR_RETURNS )
  2256. {
  2257. DBGPRINTF(( DBG_CONTEXT,
  2258. "\r\n"
  2259. " HSE_REQ_SEND_CUSTOM_ERROR[%p]: Failed\r\n"
  2260. " Another async operation is already pending\r\n"
  2261. " <END>\r\n\r\n",
  2262. pIsapiContext ));
  2263. }
  2264. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  2265. }
  2266. }
  2267. hr = pIsapiCore->SendCustomError(
  2268. pCustomErrorInfo->fAsync ? reinterpret_cast<DWORD64>( pIsapiContext ) : NULL,
  2269. pCustomErrorInfo->pszStatus,
  2270. pCustomErrorInfo->uHttpSubError );
  2271. if ( FAILED( hr ) )
  2272. {
  2273. IF_DEBUG( ISAPI_ERROR_RETURNS )
  2274. {
  2275. DBGPRINTF(( DBG_CONTEXT,
  2276. "\r\n"
  2277. " HSE_REQ_SEND_CUSTOM_ERROR[%p]: Failed\r\n"
  2278. " Error: 0x%08x\r\n"
  2279. " <END>\r\n\r\n",
  2280. pIsapiContext,
  2281. hr ));
  2282. }
  2283. if ( pCustomErrorInfo->fAsync )
  2284. {
  2285. pIsapiContext->UninitAsyncIo();
  2286. }
  2287. return hr;
  2288. }
  2289. return hr;
  2290. }
  2291. HRESULT
  2292. SSFVectorSendDeprecated(
  2293. ISAPI_CONTEXT * pIsapiContext,
  2294. HSE_RESPONSE_VECTOR_DEPRECATED * pResponseVector
  2295. )
  2296. /*++
  2297. Routine Description:
  2298. The old deprecated vector-send
  2299. Arguments:
  2300. pIsapiContext - The ISAPI_CONTEXT associated with this command.
  2301. pResponseVector - The vector to be sent
  2302. Return Value:
  2303. HRESULT
  2304. --*/
  2305. {
  2306. HSE_RESPONSE_VECTOR RealResponseVector;
  2307. STACK_BUFFER( buffResp, 512);
  2308. HRESULT hr;
  2309. IF_DEBUG( ISAPI_SSF_DETAILS )
  2310. {
  2311. DBGPRINTF(( DBG_CONTEXT,
  2312. "\r\n"
  2313. " HSE_REQ_VECTOR_SEND_DEPRECATED[%p]: Function Entry\r\n"
  2314. " <END>\r\n\r\n",
  2315. pIsapiContext ));
  2316. }
  2317. if ( pResponseVector == NULL )
  2318. {
  2319. IF_DEBUG( ISAPI_ERROR_RETURNS )
  2320. {
  2321. DBGPRINTF(( DBG_CONTEXT,
  2322. "\r\n"
  2323. " HSE_REQ_VECTOR_SEND_DEPRECATED[%p]: Parameter validation failure\r\n"
  2324. " Response Vector Ptr: NULL\r\n"
  2325. " <END>\r\n\r\n",
  2326. pIsapiContext ));
  2327. }
  2328. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  2329. }
  2330. RealResponseVector.dwFlags = pResponseVector->dwFlags;
  2331. RealResponseVector.pszStatus = pResponseVector->pszStatus;
  2332. RealResponseVector.pszHeaders = pResponseVector->pszHeaders;
  2333. RealResponseVector.nElementCount = pResponseVector->nElementCount;
  2334. if (!buffResp.Resize(pResponseVector->nElementCount * sizeof(HSE_VECTOR_ELEMENT)))
  2335. {
  2336. return HRESULT_FROM_WIN32( ERROR_NOT_ENOUGH_MEMORY );
  2337. }
  2338. RealResponseVector.lpElementArray = (HSE_VECTOR_ELEMENT *)buffResp.QueryPtr();
  2339. for (DWORD i=0; i<pResponseVector->nElementCount; i++)
  2340. {
  2341. if (pResponseVector->lpElementArray[i].pBuffer != NULL)
  2342. {
  2343. RealResponseVector.lpElementArray[i].ElementType = HSE_VECTOR_ELEMENT_TYPE_MEMORY_BUFFER;
  2344. RealResponseVector.lpElementArray[i].pvContext = pResponseVector->lpElementArray[i].pBuffer;
  2345. RealResponseVector.lpElementArray[i].cbSize = pResponseVector->lpElementArray[i].cbSize;
  2346. }
  2347. else
  2348. {
  2349. RealResponseVector.lpElementArray[i].ElementType = HSE_VECTOR_ELEMENT_TYPE_FILE_HANDLE;
  2350. RealResponseVector.lpElementArray[i].pvContext = pResponseVector->lpElementArray[i].hFile;
  2351. RealResponseVector.lpElementArray[i].cbOffset = pResponseVector->lpElementArray[i].cbOffset;
  2352. RealResponseVector.lpElementArray[i].cbSize = pResponseVector->lpElementArray[i].cbSize;
  2353. }
  2354. }
  2355. hr = SSFVectorSend(pIsapiContext, &RealResponseVector);
  2356. if ( FAILED( hr ) )
  2357. {
  2358. IF_DEBUG( ISAPI_ERROR_RETURNS )
  2359. {
  2360. DBGPRINTF(( DBG_CONTEXT,
  2361. "\r\n"
  2362. " HSE_REQ_VECTOR_SEND_DEPRECATED[%p]: Failed\r\n"
  2363. " Error: 0x%08x\r\n"
  2364. " <END>\r\n\r\n",
  2365. pIsapiContext,
  2366. hr ));
  2367. }
  2368. return hr;
  2369. }
  2370. return hr;
  2371. }
  2372. HRESULT
  2373. SSFVectorSend(
  2374. ISAPI_CONTEXT * pIsapiContext,
  2375. HSE_RESPONSE_VECTOR * pResponseVector
  2376. )
  2377. /*++
  2378. Routine Description:
  2379. Send an array of memory/file-handle/fragment-cache chunks
  2380. Arguments:
  2381. pIsapiContext - The ISAPI_CONTEXT associated with this command.
  2382. pResponseVector - The vector to be sent
  2383. Return Value:
  2384. HRESULT
  2385. --*/
  2386. {
  2387. IIsapiCore * pIsapiCore;
  2388. ULONGLONG cbTotalSend = 0;
  2389. STACK_BUFFER( buffResp, 512);
  2390. HRESULT hr = NOERROR;
  2391. DBG_ASSERT( pIsapiContext );
  2392. DBG_ASSERT( pIsapiContext->CheckSignature() );
  2393. IF_DEBUG( ISAPI_SSF_DETAILS )
  2394. {
  2395. DBGPRINTF(( DBG_CONTEXT,
  2396. "\r\n"
  2397. " HSE_REQ_VECTOR_SEND[%p]: Function Entry (%s)\r\n"
  2398. " Status: '%s'\r\n"
  2399. " Headers: '%s'\r\n"
  2400. " Element Count: %d\r\n"
  2401. " Flags: 0x%08x (%d)\r\n"
  2402. " <END>\r\n\r\n",
  2403. pIsapiContext,
  2404. pResponseVector ? pResponseVector->dwFlags & HSE_IO_ASYNC ? "Asynchronous" : "Synchronous" : "",
  2405. pResponseVector ? pResponseVector->pszStatus : NULL,
  2406. pResponseVector ? pResponseVector->pszHeaders : NULL,
  2407. pResponseVector ? pResponseVector->nElementCount : 0,
  2408. pResponseVector ? pResponseVector->dwFlags : 0,
  2409. pResponseVector ? pResponseVector->dwFlags : 0 ));
  2410. IF_DEBUG( ISAPI_DUMP_BUFFERS )
  2411. {
  2412. if ( pResponseVector &&
  2413. pResponseVector->nElementCount )
  2414. {
  2415. STACK_STRA( strBufferDump,512 );
  2416. DWORD dwBytesToDump;
  2417. DWORD i;
  2418. for ( i = 0; i < pResponseVector->nElementCount; i++ )
  2419. {
  2420. if ( pResponseVector->lpElementArray[i].ElementType == HSE_VECTOR_ELEMENT_TYPE_MEMORY_BUFFER )
  2421. {
  2422. dwBytesToDump = pResponseVector->lpElementArray[i].cbSize;
  2423. if ( dwBytesToDump > MAX_DEBUG_DUMP )
  2424. {
  2425. dwBytesToDump = MAX_DEBUG_DUMP;
  2426. }
  2427. if ( FAILED( strBufferDump.CopyBinary( pResponseVector->lpElementArray[i].pvContext, dwBytesToDump ) ) )
  2428. {
  2429. strBufferDump.Copy( "" );
  2430. }
  2431. DBGPRINTF(( DBG_CONTEXT,
  2432. "\r\n"
  2433. " HSE_REQ_VECTOR_SEND[%p]: Dump of up to %d bytes of element %d\r\n"
  2434. "%s"
  2435. " <END>\r\n\r\n",
  2436. pIsapiContext,
  2437. MAX_DEBUG_DUMP,
  2438. i,
  2439. strBufferDump.QueryStr() ));
  2440. }
  2441. else if ( pResponseVector->lpElementArray[i].ElementType == HSE_VECTOR_ELEMENT_TYPE_FILE_HANDLE )
  2442. {
  2443. DBGPRINTF(( DBG_CONTEXT,
  2444. "\r\n",
  2445. " HSE_REQ_VECTOR_SEND[%p]: Element %d\r\n"
  2446. " File Handle: %p\r\n"
  2447. " Offset: %d\r\n"
  2448. " Bytes To Send: %d\r\n"
  2449. " <END>\r\n\r\n",
  2450. pIsapiContext,
  2451. pResponseVector->lpElementArray[i].pvContext,
  2452. pResponseVector->lpElementArray[i].cbOffset,
  2453. pResponseVector->lpElementArray[i].cbSize ));
  2454. }
  2455. }
  2456. }
  2457. }
  2458. }
  2459. pIsapiCore = pIsapiContext->QueryIsapiCoreInterface();
  2460. if ( pIsapiCore == NULL )
  2461. {
  2462. IF_DEBUG( ISAPI_ERROR_RETURNS )
  2463. {
  2464. DBGPRINTF(( DBG_CONTEXT,
  2465. "\r\n"
  2466. " HSE_REQ_VECTOR_SEND[%p]: Failed to get interface to server core\r\n"
  2467. " <END>\r\n\r\n",
  2468. pIsapiContext ));
  2469. }
  2470. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  2471. }
  2472. //
  2473. // verify the data passed in
  2474. //
  2475. if ( pResponseVector == NULL ||
  2476. ( ( pResponseVector->dwFlags & HSE_IO_ASYNC ) != 0 &&
  2477. pIsapiContext->TryInitAsyncIo( AsyncVectorPending ) == FALSE ) )
  2478. {
  2479. IF_DEBUG( ISAPI_ERROR_RETURNS )
  2480. {
  2481. DBGPRINTF(( DBG_CONTEXT,
  2482. "\r\n"
  2483. " HSE_REQ_VECTOR_SEND[%p]: Failed\r\n"
  2484. " Another async operation is already pending\r\n"
  2485. " <END>\r\n\r\n",
  2486. pIsapiContext ));
  2487. }
  2488. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  2489. }
  2490. if ((pResponseVector->dwFlags & HSE_IO_SYNC) &&
  2491. (pResponseVector->dwFlags & HSE_IO_ASYNC))
  2492. {
  2493. IF_DEBUG( ISAPI_ERROR_RETURNS )
  2494. {
  2495. DBGPRINTF(( DBG_CONTEXT,
  2496. "\r\n"
  2497. " HSE_REQ_VECTOR_SEND[%p]: Parameter validation failure\r\n"
  2498. " Both HSE_IO_SYNC and HSE_IO_ASYNC were specified\r\n"
  2499. " <END>\r\n\r\n",
  2500. pIsapiContext ));
  2501. }
  2502. hr = HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  2503. goto Failed;
  2504. }
  2505. if (pResponseVector->dwFlags & HSE_IO_SEND_HEADERS)
  2506. {
  2507. if ((pResponseVector->pszStatus == NULL) ||
  2508. (pResponseVector->pszHeaders == NULL))
  2509. {
  2510. IF_DEBUG( ISAPI_ERROR_RETURNS )
  2511. {
  2512. DBGPRINTF(( DBG_CONTEXT,
  2513. "\r\n"
  2514. " HSE_REQ_VECTOR_SEND[%p]: Parameter validation failure\r\n"
  2515. " HSE_IO_SEND_HEADERS was specified, but some required info is missing\r\n"
  2516. " Status: '%s'\r\n"
  2517. " Headers: '%s'\r\n"
  2518. " <END>\r\n\r\n",
  2519. pIsapiContext,
  2520. pResponseVector->pszStatus,
  2521. pResponseVector->pszHeaders ));
  2522. }
  2523. hr = HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  2524. goto Failed;
  2525. }
  2526. }
  2527. else
  2528. {
  2529. if ((pResponseVector->pszStatus != NULL) ||
  2530. (pResponseVector->pszHeaders != NULL))
  2531. {
  2532. IF_DEBUG( ISAPI_ERROR_RETURNS )
  2533. {
  2534. DBGPRINTF(( DBG_CONTEXT,
  2535. "\r\n"
  2536. " HSE_REQ_VECTOR_SEND[%p]: Parameter validation failure\r\n"
  2537. " HSE_IO_SEND_HEADERS was not specified, yet status or header info was provided\r\n"
  2538. " Status: '%s'\r\n"
  2539. " Headers: '%s'\r\n"
  2540. " <END>\r\n\r\n",
  2541. pIsapiContext,
  2542. pResponseVector->pszStatus,
  2543. pResponseVector->pszHeaders ));
  2544. }
  2545. hr = HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  2546. goto Failed;
  2547. }
  2548. }
  2549. if (!buffResp.Resize(pResponseVector->nElementCount * sizeof(VECTOR_ELEMENT)))
  2550. {
  2551. hr = HRESULT_FROM_WIN32( ERROR_NOT_ENOUGH_MEMORY );
  2552. goto Failed;
  2553. }
  2554. ZeroMemory(buffResp.QueryPtr(),
  2555. pResponseVector->nElementCount * sizeof(VECTOR_ELEMENT));
  2556. VECTOR_ELEMENT *pVectorElement = (VECTOR_ELEMENT *)buffResp.QueryPtr();
  2557. HSE_VECTOR_ELEMENT *pHseVectorElement;
  2558. for (DWORD i=0; i<pResponseVector->nElementCount; i++)
  2559. {
  2560. pHseVectorElement = &pResponseVector->lpElementArray[i];
  2561. if (pHseVectorElement->pvContext == NULL)
  2562. {
  2563. IF_DEBUG( ISAPI_ERROR_RETURNS )
  2564. {
  2565. DBGPRINTF(( DBG_CONTEXT,
  2566. "\r\n"
  2567. " HSE_REQ_VECTOR_SEND[%p]: Parameter validation failure\r\n"
  2568. " Context: NULL on element %d in the array\r\n"
  2569. " <END>\r\n\r\n",
  2570. pIsapiContext,
  2571. i ));
  2572. }
  2573. hr = HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  2574. goto Failed;
  2575. }
  2576. switch (pHseVectorElement->ElementType)
  2577. {
  2578. case HSE_VECTOR_ELEMENT_TYPE_MEMORY_BUFFER:
  2579. if (pHseVectorElement->cbSize > MAXULONG)
  2580. {
  2581. IF_DEBUG( ISAPI_ERROR_RETURNS )
  2582. {
  2583. DBGPRINTF(( DBG_CONTEXT,
  2584. "\r\n"
  2585. " HSE_REQ_VECTOR_SEND[%p]: Parameter validation failure\r\n"
  2586. " Invalid memory buffer size on element %d in the array\r\n"
  2587. " Size: %d\r\n"
  2588. " <END>\r\n\r\n",
  2589. pIsapiContext,
  2590. i,
  2591. pHseVectorElement->cbSize ));
  2592. }
  2593. hr = HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  2594. goto Failed;
  2595. }
  2596. pVectorElement[i].pBuffer = (BYTE *)pHseVectorElement->pvContext;
  2597. cbTotalSend += ( pVectorElement[i].cbBufSize = (DWORD)pHseVectorElement->cbSize );
  2598. break;
  2599. case HSE_VECTOR_ELEMENT_TYPE_FILE_HANDLE:
  2600. if (pHseVectorElement->pvContext == INVALID_HANDLE_VALUE)
  2601. {
  2602. IF_DEBUG( ISAPI_ERROR_RETURNS )
  2603. {
  2604. DBGPRINTF(( DBG_CONTEXT,
  2605. "\r\n"
  2606. " HSE_REQ_VECTOR_SEND[%p]: Parameter validation failure\r\n"
  2607. " Handle on file handle element %d in the array is invalid\r\n"
  2608. " File Handle: %p\r\n"
  2609. " <END>\r\n\r\n",
  2610. pIsapiContext,
  2611. i,
  2612. pHseVectorElement->pvContext ));
  2613. }
  2614. hr = HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  2615. goto Failed;
  2616. }
  2617. //
  2618. // Treat 0 as "send the rest of the file" - same as TransmitFile
  2619. //
  2620. if (pHseVectorElement->cbSize == 0)
  2621. {
  2622. pHseVectorElement->cbSize = HTTP_BYTE_RANGE_TO_EOF;
  2623. }
  2624. pVectorElement[i].hFile = (DWORD_PTR)pHseVectorElement->pvContext;
  2625. pVectorElement[i].cbOffset = pHseVectorElement->cbOffset;
  2626. cbTotalSend += ( pVectorElement[i].cbFileSize = pHseVectorElement->cbSize );
  2627. break;
  2628. case HSE_VECTOR_ELEMENT_TYPE_FRAGMENT:
  2629. pVectorElement[i].pszFragmentName = (WCHAR *)pHseVectorElement->pvContext;
  2630. break;
  2631. default:
  2632. IF_DEBUG( ISAPI_ERROR_RETURNS )
  2633. {
  2634. DBGPRINTF(( DBG_CONTEXT,
  2635. "\r\n"
  2636. " HSE_REQ_VECTOR_SEND[%p]: Parameter validation failure\r\n"
  2637. " Unknown type on element %d in the array\r\n"
  2638. " Element Type: %d\r\n"
  2639. " <END>\r\n\r\n",
  2640. pIsapiContext,
  2641. i,
  2642. pHseVectorElement->ElementType ));
  2643. }
  2644. hr = HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER);
  2645. goto Failed;
  2646. }
  2647. }
  2648. //
  2649. // Set up the total number of bytes we are trying to send so that ISAPIs
  2650. // are not confused
  2651. //
  2652. pIsapiContext->SetLastAsyncIo( (cbTotalSend > MAXULONG) ? MAXULONG : (DWORD)cbTotalSend );
  2653. //
  2654. // In general, VECTOR_SEND shouldn't touch the connection flags
  2655. // in the ISAPI_CONTEXT, since ISAPI tries to do the right thing
  2656. // automatically.
  2657. //
  2658. // There are couple of scenarios, though, where we might have a
  2659. // bit of connection management housekeeping to do.
  2660. //
  2661. // If the caller specified the HSE_IO_DISCONNECT_AFTER_SEND flag,
  2662. // then we need to force the connection closed.
  2663. //
  2664. // Otherwise, there are two scenarios where we may need to force
  2665. // the connection to stay open.
  2666. //
  2667. // First, if all of the below are true, we should set the
  2668. // connection to be open:
  2669. //
  2670. // - The client requested keep-alive
  2671. // - This call is sending headers (HSE_IO_SEND_HEADERS is set)
  2672. // - The disconnect flag has not been set
  2673. //
  2674. // Second, if all of the below are true, we should set the
  2675. // connection to be open.
  2676. //
  2677. // - The client requested keep-alive
  2678. // - The ISAPI has not already sent headers
  2679. // - The disconnect flag has not been set
  2680. // - This is the final send
  2681. //
  2682. // One final note: This logic does not account for the case where
  2683. // this call is sending headers, and the call fails for some reason.
  2684. // In the asynchronous case, this would be somewhat complicated to
  2685. // handle, since the completion routine would need to know both if
  2686. // the caller was sending headers, and also that the I/O failed.
  2687. // Presumably, if such a failure occurs, the most likely reason is
  2688. // that the client already disconnected, or it would otherwise be
  2689. // unlikely for the caller to do something to try and recover and
  2690. // redo this send in a way that would succeed, which makes all of this
  2691. // moot.
  2692. //
  2693. if ( pResponseVector->dwFlags & HSE_IO_DISCONNECT_AFTER_SEND )
  2694. {
  2695. pIsapiContext->SetKeepConn( FALSE );
  2696. }
  2697. else
  2698. {
  2699. if ( pIsapiContext->QueryClientKeepConn() )
  2700. {
  2701. if ( (pResponseVector->dwFlags & HSE_IO_SEND_HEADERS) ||
  2702. ( pIsapiContext->QueryHeadersSent() == FALSE &&
  2703. (pResponseVector->dwFlags & HSE_IO_FINAL_SEND) ) )
  2704. {
  2705. pIsapiContext->SetKeepConn( TRUE );
  2706. }
  2707. }
  2708. }
  2709. hr = pIsapiCore->VectorSend(
  2710. pResponseVector->dwFlags & HSE_IO_ASYNC ? reinterpret_cast<DWORD64>( pIsapiContext ) : NULL,
  2711. !pIsapiContext->QueryKeepConn(),
  2712. pResponseVector->pszStatus,
  2713. pResponseVector->pszHeaders,
  2714. pVectorElement,
  2715. pResponseVector->nElementCount,
  2716. !!(pResponseVector->dwFlags & HSE_IO_FINAL_SEND),
  2717. !!(pResponseVector->dwFlags & HSE_IO_CACHE_RESPONSE)
  2718. );
  2719. if ( FAILED( hr ) )
  2720. {
  2721. goto Failed;
  2722. }
  2723. return hr;
  2724. Failed:
  2725. DBG_ASSERT( FAILED( hr ) );
  2726. IF_DEBUG( ISAPI_ERROR_RETURNS )
  2727. {
  2728. DBGPRINTF(( DBG_CONTEXT,
  2729. "\r\n"
  2730. " HSE_REQ_VECTOR_SEND[%p]: Failed\r\n"
  2731. " Error: 0x%08x\r\n"
  2732. " <END>\r\n\r\n",
  2733. pIsapiContext,
  2734. hr ));
  2735. }
  2736. if ( pResponseVector->dwFlags & HSE_IO_ASYNC )
  2737. {
  2738. pIsapiContext->SetLastAsyncIo( 0 );
  2739. pIsapiContext->UninitAsyncIo();
  2740. }
  2741. return hr;
  2742. }
  2743. HRESULT
  2744. SSFGetCustomErrorPage(
  2745. ISAPI_CONTEXT * pIsapiContext,
  2746. HSE_CUSTOM_ERROR_PAGE_INFO * pInfo
  2747. )
  2748. {
  2749. IIsapiCore * pIsapiCore;
  2750. HRESULT hr;
  2751. DBG_ASSERT( pIsapiContext );
  2752. DBG_ASSERT( pIsapiContext->CheckSignature() );
  2753. IF_DEBUG( ISAPI_SSF_DETAILS )
  2754. {
  2755. DBGPRINTF(( DBG_CONTEXT,
  2756. "\r\n"
  2757. " HSE_REQ_GET_CUSTOM_ERROR_PAGE[%p]: Function Entry\r\n"
  2758. " Error: %d\r\n"
  2759. " SubError: %d\r\n"
  2760. " <END>\r\n\r\n",
  2761. pIsapiContext,
  2762. pInfo ? pInfo->dwError : 0,
  2763. pInfo ? pInfo->dwSubError : 0 ));
  2764. }
  2765. pIsapiCore = pIsapiContext->QueryIsapiCoreInterface();
  2766. if ( pIsapiCore == NULL )
  2767. {
  2768. IF_DEBUG( ISAPI_ERROR_RETURNS )
  2769. {
  2770. DBGPRINTF(( DBG_CONTEXT,
  2771. "\r\n"
  2772. " HSE_REQ_GET_CUSTOM_ERROR_PAGE[%p]: Failed to get interface to server core\r\n"
  2773. " <END>\r\n\r\n",
  2774. pIsapiContext ));
  2775. }
  2776. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  2777. }
  2778. //
  2779. // Validate arguments
  2780. //
  2781. if ( pInfo == NULL ||
  2782. ( pInfo->dwBufferSize != 0 && pInfo->pBuffer == NULL ) ||
  2783. pInfo->pdwBufferRequired == NULL ||
  2784. pInfo->pfIsFileError == NULL )
  2785. {
  2786. IF_DEBUG( ISAPI_ERROR_RETURNS )
  2787. {
  2788. DBGPRINTF(( DBG_CONTEXT,
  2789. "\r\n"
  2790. " HSE_REQ_GET_CUSTOM_ERROR_PAGE[%p]: Parameter validation failure\r\n"
  2791. " Info Ptr: %p\r\n"
  2792. " Buffer Size: %d\r\n"
  2793. " Buffer Ptr: %p\r\n"
  2794. " Buffer Required Ptr: %p\r\n"
  2795. " IsFileError Ptr: %p\r\n"
  2796. " <END>\r\n\r\n",
  2797. pIsapiContext,
  2798. pInfo,
  2799. pInfo ? pInfo->dwBufferSize : 0,
  2800. pInfo ? pInfo->pBuffer : NULL,
  2801. pInfo ? pInfo->pdwBufferRequired : NULL,
  2802. pInfo ? pInfo->pfIsFileError : NULL ));
  2803. }
  2804. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  2805. }
  2806. hr = pIsapiCore->GetCustomError(
  2807. pInfo->dwError,
  2808. pInfo->dwSubError,
  2809. pInfo->dwBufferSize,
  2810. reinterpret_cast<BYTE*>( pInfo->pBuffer ),
  2811. pInfo->pdwBufferRequired,
  2812. pInfo->pfIsFileError,
  2813. pInfo->pfSendErrorBody
  2814. );
  2815. if ( FAILED( hr ) )
  2816. {
  2817. IF_DEBUG( ISAPI_ERROR_RETURNS )
  2818. {
  2819. DBGPRINTF(( DBG_CONTEXT,
  2820. "\r\n"
  2821. " HSE_REQ_GET_CUSTOM_ERROR_PAGE[%p]: Failed\r\n"
  2822. " Error: 0x%08x\r\n"
  2823. " <END>\r\n\r\n",
  2824. pIsapiContext,
  2825. hr ));
  2826. }
  2827. return hr;
  2828. }
  2829. return hr;
  2830. }
  2831. HRESULT
  2832. SSFIsInProcess(
  2833. ISAPI_CONTEXT * pIsapiContext,
  2834. DWORD * pdwAppFlag
  2835. )
  2836. {
  2837. LPWSTR szClsid;
  2838. DBG_ASSERT( pIsapiContext );
  2839. DBG_ASSERT( pIsapiContext->CheckSignature() );
  2840. IF_DEBUG( ISAPI_SSF_DETAILS )
  2841. {
  2842. DBGPRINTF(( DBG_CONTEXT,
  2843. "\r\n"
  2844. " HSE_REQ_IS_IN_PROCESS[%p]: Function Entry\r\n"
  2845. " <END>\r\n\r\n",
  2846. pIsapiContext ));
  2847. }
  2848. if ( pdwAppFlag == NULL )
  2849. {
  2850. IF_DEBUG( ISAPI_ERROR_RETURNS )
  2851. {
  2852. DBGPRINTF(( DBG_CONTEXT,
  2853. "\r\n"
  2854. " HSE_REQ_IS_IN_PROCESS[%p]: Parameter validation failure\r\n"
  2855. " AppFlag Ptr: NULL\r\n"
  2856. " <END>\r\n\r\n",
  2857. pIsapiContext ));
  2858. }
  2859. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  2860. }
  2861. szClsid = pIsapiContext->QueryClsid();
  2862. DBG_ASSERT( szClsid != NULL );
  2863. if ( wcslen( szClsid ) == 0 )
  2864. {
  2865. *pdwAppFlag = HSE_APP_FLAG_IN_PROCESS;
  2866. }
  2867. else if ( _wcsicmp( szClsid, W3_OOP_POOL_WAM_CLSID ) == NULL )
  2868. {
  2869. *pdwAppFlag = HSE_APP_FLAG_POOLED_OOP;
  2870. }
  2871. else
  2872. {
  2873. *pdwAppFlag = HSE_APP_FLAG_ISOLATED_OOP;
  2874. }
  2875. return NO_ERROR;
  2876. }
  2877. HRESULT
  2878. SSFGetSspiInfo(
  2879. ISAPI_CONTEXT * pIsapiContext,
  2880. CtxtHandle * pCtxtHandle,
  2881. CredHandle * pCredHandle
  2882. )
  2883. {
  2884. IIsapiCore * pIsapiCore;
  2885. HRESULT hr;
  2886. DBG_ASSERT( pIsapiContext );
  2887. DBG_ASSERT( pIsapiContext->CheckSignature() );
  2888. DBG_REQUIRE( ( pIsapiCore = pIsapiContext->QueryIsapiCoreInterface() ) != NULL );
  2889. IF_DEBUG( ISAPI_SSF_DETAILS )
  2890. {
  2891. DBGPRINTF(( DBG_CONTEXT,
  2892. "\r\n"
  2893. " HSE_REQ_GET_SSPI_INFO[%p]: Function Entry\r\n"
  2894. " <END>\r\n\r\n",
  2895. pIsapiContext ));
  2896. }
  2897. //
  2898. // The CtxtHandle and CredHandle are only valid in their
  2899. // local process. There is no way to duplicate them into
  2900. // a dllhost. As a result, this function is inproc only.
  2901. //
  2902. if ( pIsapiContext->QueryIsOop() )
  2903. {
  2904. return HRESULT_FROM_WIN32( ERROR_INVALID_FUNCTION );
  2905. }
  2906. //
  2907. // Validate parameters
  2908. //
  2909. if ( pCtxtHandle == NULL || pCredHandle == NULL )
  2910. {
  2911. IF_DEBUG( ISAPI_ERROR_RETURNS )
  2912. {
  2913. DBGPRINTF(( DBG_CONTEXT,
  2914. "\r\n"
  2915. " HSE_REQ_GET_SSPI_INFO[%p]: Parameter validation Failure\r\n"
  2916. " Context Handle Ptr: %p\r\n"
  2917. " Credential Handle Ptr: %p\r\n"
  2918. " <END>\r\n\r\n",
  2919. pIsapiContext,
  2920. pCtxtHandle,
  2921. pCredHandle ));
  2922. }
  2923. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  2924. }
  2925. hr = pIsapiCore->GetSspiInfo(
  2926. reinterpret_cast<BYTE*>( pCredHandle ),
  2927. sizeof( CredHandle ),
  2928. reinterpret_cast<BYTE*>( pCtxtHandle ),
  2929. sizeof( CtxtHandle )
  2930. );
  2931. if ( FAILED( hr ) )
  2932. {
  2933. IF_DEBUG( ISAPI_ERROR_RETURNS )
  2934. {
  2935. DBGPRINTF(( DBG_CONTEXT,
  2936. "\r\n"
  2937. " HSE_REQ_GET_SSPI_INFO[%p]: Failed\r\n"
  2938. " Error: 0x%08x\r\n"
  2939. " <END>\r\n\r\n",
  2940. pIsapiContext,
  2941. hr ));
  2942. }
  2943. return hr;
  2944. }
  2945. return hr;
  2946. }
  2947. HRESULT
  2948. SSFGetVirtualPathToken(
  2949. ISAPI_CONTEXT * pIsapiContext,
  2950. LPSTR szUrl,
  2951. HANDLE * pToken,
  2952. BOOL fUnicode
  2953. )
  2954. {
  2955. IIsapiCore * pIsapiCore;
  2956. HRESULT hr = S_OK;
  2957. DWORD64 dwToken;
  2958. DBG_ASSERT( pIsapiContext );
  2959. DBG_ASSERT( pIsapiContext->CheckSignature() );
  2960. DBG_REQUIRE( ( pIsapiCore = pIsapiContext->QueryIsapiCoreInterface() ) != NULL );
  2961. IF_DEBUG( ISAPI_SSF_DETAILS )
  2962. {
  2963. if ( fUnicode )
  2964. {
  2965. DBGPRINTF(( DBG_CONTEXT,
  2966. "\r\n"
  2967. " HSE_REQ_GET_UNICODE_VIRTUAL_PATH_TOKEN[%p]: Function Entry\r\n"
  2968. " URL: '%S'\r\n"
  2969. " <END>\r\n\r\n",
  2970. pIsapiContext,
  2971. szUrl ));
  2972. }
  2973. else
  2974. {
  2975. DBGPRINTF(( DBG_CONTEXT,
  2976. "\r\n"
  2977. " HSE_REQ_GET_VIRTUAL_PATH_TOKEN[%p]: Function Entry\r\n"
  2978. " URL: '%s'\r\n"
  2979. " <END>\r\n\r\n",
  2980. pIsapiContext,
  2981. szUrl ));
  2982. }
  2983. }
  2984. //
  2985. // Validate parameters
  2986. //
  2987. if ( szUrl == NULL || pToken == NULL )
  2988. {
  2989. IF_DEBUG( ISAPI_ERROR_RETURNS )
  2990. {
  2991. if ( fUnicode )
  2992. {
  2993. DBGPRINTF(( DBG_CONTEXT,
  2994. "\r\n"
  2995. " HSE_REQ_GET_UNICODE_VIRTUAL_PATH_TOKEN[%p]: Parameter validation failure\r\n"
  2996. " URL: '%S'\r\n"
  2997. " Token Ptr: %p\r\n"
  2998. " <END>\r\n\r\n",
  2999. pIsapiContext,
  3000. szUrl,
  3001. pToken ));
  3002. }
  3003. else
  3004. {
  3005. IF_DEBUG( ISAPI_ERROR_RETURNS )
  3006. {
  3007. DBGPRINTF(( DBG_CONTEXT,
  3008. "\r\n"
  3009. " HSE_REQ_GET_VIRTUAL_PATH_TOKEN[%p]: Parameter validation failure\r\n"
  3010. " URL: '%s'\r\n"
  3011. " Token Ptr: %p\r\n"
  3012. " <END>\r\n\r\n",
  3013. pIsapiContext,
  3014. szUrl,
  3015. pToken ));
  3016. }
  3017. }
  3018. }
  3019. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  3020. }
  3021. hr = pIsapiCore->QueryToken(
  3022. reinterpret_cast<BYTE*>( szUrl ),
  3023. (DWORD)( fUnicode ? (wcslen( (LPWSTR)szUrl ) + 1 ) * sizeof(WCHAR) : strlen( szUrl ) + 1 ),
  3024. TOKEN_VR_TOKEN,
  3025. &dwToken,
  3026. fUnicode
  3027. );
  3028. if (FAILED(hr))
  3029. {
  3030. IF_DEBUG( ISAPI_ERROR_RETURNS )
  3031. {
  3032. DBGPRINTF(( DBG_CONTEXT,
  3033. "\r\n"
  3034. " HSE_REQ_GET_%sVIRTUAL_PATH_TOKEN[%p]: Failed\r\n"
  3035. " Error: 0x%08x\r\n"
  3036. " <END>\r\n\r\n",
  3037. fUnicode ? "UNICODE_" : "",
  3038. pIsapiContext,
  3039. hr ));
  3040. }
  3041. return hr;
  3042. }
  3043. *pToken = (HANDLE)dwToken;
  3044. return hr;
  3045. }
  3046. HRESULT
  3047. SSFGetAnonymousToken(
  3048. ISAPI_CONTEXT * pIsapiContext,
  3049. LPSTR szUrl,
  3050. HANDLE * pToken,
  3051. BOOL fUnicode
  3052. )
  3053. {
  3054. IIsapiCore * pIsapiCore;
  3055. DWORD64 dwToken;
  3056. HRESULT hr;
  3057. DBG_ASSERT( pIsapiContext );
  3058. DBG_ASSERT( pIsapiContext->CheckSignature() );
  3059. DBG_REQUIRE( ( pIsapiCore = pIsapiContext->QueryIsapiCoreInterface() ) != NULL );
  3060. IF_DEBUG( ISAPI_SSF_DETAILS )
  3061. {
  3062. if ( fUnicode )
  3063. {
  3064. DBGPRINTF(( DBG_CONTEXT,
  3065. "\r\n"
  3066. " HSE_REQ_GET_UNICODE_ANONYMOUS_TOKEN[%p]: Function Entry\r\n"
  3067. " URL: '%S'\r\n"
  3068. " <END>\r\n\r\n",
  3069. pIsapiContext,
  3070. szUrl ));
  3071. }
  3072. else
  3073. {
  3074. DBGPRINTF(( DBG_CONTEXT,
  3075. "\r\n"
  3076. " HSE_REQ_GET_ANONYMOUS_TOKEN[%p]: Function Entry\r\n"
  3077. " URL: '%s\r\n"
  3078. " <END>\r\n\r\n",
  3079. pIsapiContext,
  3080. szUrl ));
  3081. }
  3082. }
  3083. //
  3084. // Validate parameters
  3085. //
  3086. if ( szUrl == NULL || pToken == NULL )
  3087. {
  3088. if ( fUnicode )
  3089. {
  3090. IF_DEBUG( ISAPI_ERROR_RETURNS )
  3091. {
  3092. DBGPRINTF(( DBG_CONTEXT,
  3093. "\r\n"
  3094. " HSE_REQ_GET_UNICODE_ANONYMOUS_TOKEN[%p]: Parameter validation failure\r\n"
  3095. " URL: '%S'\r\n"
  3096. " Token Ptr: %p\r\n"
  3097. " <END>\r\n\r\n",
  3098. pIsapiContext,
  3099. szUrl,
  3100. pToken ));
  3101. }
  3102. }
  3103. else
  3104. {
  3105. IF_DEBUG( ISAPI_ERROR_RETURNS )
  3106. {
  3107. DBGPRINTF(( DBG_CONTEXT,
  3108. "\r\n"
  3109. " HSE_REQ_GET_ANONYMOUS_TOKEN[%p]: Parameter validation failure\r\n"
  3110. " URL: '%s'\r\n"
  3111. " Token Ptr: %p\r\n"
  3112. " <END>\r\n\r\n",
  3113. pIsapiContext,
  3114. szUrl,
  3115. pToken ));
  3116. }
  3117. }
  3118. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  3119. }
  3120. hr = pIsapiCore->QueryToken(
  3121. reinterpret_cast<BYTE*>( szUrl ),
  3122. (DWORD)( fUnicode ? (wcslen( (LPWSTR)szUrl ) + 1 ) * sizeof(WCHAR) : strlen( szUrl ) + 1 ),
  3123. TOKEN_ANONYMOUS_TOKEN,
  3124. &dwToken,
  3125. fUnicode
  3126. );
  3127. if ( FAILED( hr ) )
  3128. {
  3129. IF_DEBUG( ISAPI_ERROR_RETURNS )
  3130. {
  3131. DBGPRINTF(( DBG_CONTEXT,
  3132. "\r\n"
  3133. " HSE_REQ_GET_%sANONYMOUS_TOKEN[%p]: Failed\r\n"
  3134. " Error: 0x%08x\r\n"
  3135. " <END>\r\n\r\n",
  3136. fUnicode ? "UNICODE_" : "",
  3137. pIsapiContext,
  3138. hr ));
  3139. }
  3140. return hr;
  3141. }
  3142. *pToken = (HANDLE)dwToken;
  3143. return hr;
  3144. }
  3145. HRESULT
  3146. SSFReportUnhealthy(
  3147. ISAPI_CONTEXT * pIsapiContext,
  3148. LPSTR szReason
  3149. )
  3150. {
  3151. IIsapiCore * pIsapiCore;
  3152. LPWSTR szImage;
  3153. STACK_STRU( strReason, 512 );
  3154. DWORD cbImage;
  3155. DWORD cbReason;
  3156. HRESULT hr;
  3157. DBG_ASSERT( pIsapiContext );
  3158. DBG_ASSERT( pIsapiContext->CheckSignature() );
  3159. DBG_REQUIRE( ( pIsapiCore = pIsapiContext->QueryIsapiCoreInterface() ) != NULL );
  3160. DBG_REQUIRE( ( szImage = pIsapiContext->QueryGatewayImage() ) != NULL );
  3161. IF_DEBUG( ISAPI_SSF_DETAILS )
  3162. {
  3163. DBGPRINTF(( DBG_CONTEXT,
  3164. "\r\n"
  3165. " HSE_REQ_REPORT_UNHEALTHY[%p]: Function Entry\r\n"
  3166. " Reason: '%s'\r\n"
  3167. " <END>\r\n\r\n",
  3168. pIsapiContext,
  3169. szReason ));
  3170. }
  3171. cbImage = (DWORD)( wcslen( szImage ) + 1 ) * sizeof( WCHAR );
  3172. //
  3173. // If the ISAPI has given a reason, we need to send it
  3174. // as UNICODE.
  3175. //
  3176. if ( szReason == NULL )
  3177. {
  3178. cbReason = 0;
  3179. }
  3180. else
  3181. {
  3182. hr = strReason.CopyA( szReason );
  3183. if ( FAILED( hr ) )
  3184. {
  3185. return hr;
  3186. }
  3187. cbReason = ( strReason.QueryCCH() + 1 ) * sizeof( WCHAR );
  3188. }
  3189. hr = pIsapiCore->ReportAsUnhealthy(
  3190. reinterpret_cast<BYTE*>( szImage ),
  3191. cbImage,
  3192. cbReason ? reinterpret_cast<BYTE*>( strReason.QueryStr() ) : NULL,
  3193. cbReason
  3194. );
  3195. if ( FAILED( hr ) )
  3196. {
  3197. IF_DEBUG( ISAPI_ERROR_RETURNS )
  3198. {
  3199. DBGPRINTF(( DBG_CONTEXT,
  3200. "\r\n"
  3201. " HSE_REQ_REPORT_UNHEALTHY[%p]: Failed\r\n"
  3202. " Error: 0x%08x\r\n"
  3203. " <END>\r\n\r\n",
  3204. pIsapiContext,
  3205. hr ));
  3206. }
  3207. return hr;
  3208. }
  3209. return hr;
  3210. }
  3211. HRESULT
  3212. SSFNormalizeUrl(
  3213. LPSTR pszURL
  3214. )
  3215. /*++
  3216. Routine Description:
  3217. Normalize URL
  3218. Arguments:
  3219. pszURL - On entry, contains not normalized URL. On return,
  3220. contains normalized URL.
  3221. Return Value:
  3222. HRESULT
  3223. --*/
  3224. {
  3225. HRESULT hr;
  3226. IF_DEBUG( ISAPI_SSF_DETAILS )
  3227. {
  3228. DBGPRINTF(( DBG_CONTEXT,
  3229. "\r\n"
  3230. " HSE_REQ_NORMALIZE_URL[]: Function Entry\r\n"
  3231. " URL: '%s'\r\n"
  3232. " <END>\r\n\r\n",
  3233. pszURL ));
  3234. }
  3235. //
  3236. // Validate parameters
  3237. //
  3238. if ( pszURL == NULL )
  3239. {
  3240. IF_DEBUG( ISAPI_ERROR_RETURNS )
  3241. {
  3242. DBGPRINTF(( DBG_CONTEXT,
  3243. "\r\n"
  3244. " HSE_REQ_NORMALIZE_URL[]: Parameter validation failure\r\n"
  3245. " URL: NULL\r\n"
  3246. " <END>\r\n\r\n" ));
  3247. }
  3248. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  3249. }
  3250. hr = NormalizeUrl( pszURL );
  3251. if ( FAILED( hr ) )
  3252. {
  3253. IF_DEBUG( ISAPI_ERROR_RETURNS )
  3254. {
  3255. DBGPRINTF(( DBG_CONTEXT,
  3256. "\r\n"
  3257. " HSE_REQ_NORMALIZE_URL[]: Failed\r\n"
  3258. " Error: 0x%08x\r\n"
  3259. " <END>\r\n\r\n",
  3260. hr ));
  3261. }
  3262. return hr;
  3263. }
  3264. return hr;
  3265. }
  3266. HRESULT
  3267. SSFAddFragmentToCache(
  3268. ISAPI_CONTEXT * pIsapiContext,
  3269. HSE_VECTOR_ELEMENT * pHseVectorElement,
  3270. WCHAR * pszFragmentName
  3271. )
  3272. /*++
  3273. Routine Description:
  3274. Add the given fragment to the fragment-cache
  3275. Arguments:
  3276. pIsapiContext - The ISAPI_CONTEXT associated with this command.
  3277. pVectorElement - The fragment to be added
  3278. pszFragmentName - The name of the fragment
  3279. Return Value:
  3280. HRESULT
  3281. --*/
  3282. {
  3283. IIsapiCore *pIsapiCore = pIsapiContext->QueryIsapiCoreInterface();
  3284. HRESULT hr;
  3285. IF_DEBUG( ISAPI_SSF_DETAILS )
  3286. {
  3287. DBGPRINTF(( DBG_CONTEXT,
  3288. "\r\n"
  3289. " HSE_REQ_ADD_FRAGMENT_TO_CACHE[%p]: Function Entry\r\n"
  3290. " Fragment Name: '%S'\r\n"
  3291. " <END>\r\n\r\n",
  3292. pIsapiContext,
  3293. pszFragmentName ));
  3294. }
  3295. if ( pIsapiCore == NULL )
  3296. {
  3297. IF_DEBUG( ISAPI_ERROR_RETURNS )
  3298. {
  3299. DBGPRINTF(( DBG_CONTEXT,
  3300. "\r\n"
  3301. " HSE_REQ_ADD_FRAGMENT_TO_CACHE[%p]: Failed to get interface to server core\r\n"
  3302. " <END>\r\n\r\n",
  3303. pIsapiContext ));
  3304. }
  3305. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  3306. }
  3307. //
  3308. // verify the data passed in
  3309. //
  3310. if ( pHseVectorElement == NULL ||
  3311. pszFragmentName == NULL )
  3312. {
  3313. IF_DEBUG( ISAPI_ERROR_RETURNS )
  3314. {
  3315. DBGPRINTF(( DBG_CONTEXT,
  3316. "\r\n"
  3317. " HSE_REQ_ADD_FRAGMENT_TO_CACHE[%p]: Parameter validation failure\r\n"
  3318. " Vector Element Ptr: %p\r\n"
  3319. " Fragment Name: '%s'\r\n"
  3320. " <END>\r\n\r\n",
  3321. pIsapiContext,
  3322. pHseVectorElement,
  3323. pszFragmentName ));
  3324. }
  3325. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  3326. }
  3327. VECTOR_ELEMENT VectorElement;
  3328. ZeroMemory(&VectorElement, sizeof VectorElement);
  3329. if (pHseVectorElement->pvContext == NULL)
  3330. {
  3331. IF_DEBUG( ISAPI_ERROR_RETURNS )
  3332. {
  3333. DBGPRINTF(( DBG_CONTEXT,
  3334. "\r\n"
  3335. " HSE_REQ_ADD_FRAGMENT_TO_CACHE[%p]: Parameter validation failure\r\n"
  3336. " Vector Element Context: NULL\r\n"
  3337. " <END>\r\n\r\n",
  3338. pIsapiContext ));
  3339. }
  3340. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  3341. }
  3342. switch (pHseVectorElement->ElementType)
  3343. {
  3344. case HSE_VECTOR_ELEMENT_TYPE_MEMORY_BUFFER:
  3345. if (pHseVectorElement->cbSize > MAXULONG)
  3346. {
  3347. IF_DEBUG( ISAPI_ERROR_RETURNS )
  3348. {
  3349. DBGPRINTF(( DBG_CONTEXT,
  3350. "\r\n"
  3351. " HSE_REQ_ADD_FRAGMENT_TO_CACHE[%p]: Parameter validation failure\r\n"
  3352. " Memory buffer size element invalid\r\n"
  3353. " Size: %d\r\n"
  3354. " <END>\r\n\r\n",
  3355. pIsapiContext,
  3356. pHseVectorElement->cbSize ));
  3357. }
  3358. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  3359. }
  3360. VectorElement.pBuffer = (BYTE *)pHseVectorElement->pvContext;
  3361. VectorElement.cbBufSize = (DWORD)pHseVectorElement->cbSize;
  3362. break;
  3363. case HSE_VECTOR_ELEMENT_TYPE_FILE_HANDLE:
  3364. if (pHseVectorElement->pvContext == INVALID_HANDLE_VALUE)
  3365. {
  3366. IF_DEBUG( ISAPI_ERROR_RETURNS )
  3367. {
  3368. DBGPRINTF(( DBG_CONTEXT,
  3369. "\r\n"
  3370. " HSE_REQ_ADD_FRAGMENT_TO_CACHE[%p]: Parameter validation failure\r\n"
  3371. " Element file handle invalid\r\n"
  3372. " File Handle: %p\r\n"
  3373. " <END>\r\n\r\n",
  3374. pIsapiContext,
  3375. pHseVectorElement->pvContext ));
  3376. }
  3377. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  3378. }
  3379. //
  3380. // Treat 0 as "send the rest of the file" - same as TransmitFile/VectorSend
  3381. //
  3382. if (pHseVectorElement->cbSize == 0)
  3383. {
  3384. pHseVectorElement->cbSize = HTTP_BYTE_RANGE_TO_EOF;
  3385. }
  3386. VectorElement.hFile = (DWORD_PTR)pHseVectorElement->pvContext;
  3387. VectorElement.cbOffset = pHseVectorElement->cbOffset;
  3388. VectorElement.cbFileSize = pHseVectorElement->cbSize;
  3389. break;
  3390. case HSE_VECTOR_ELEMENT_TYPE_FRAGMENT:
  3391. default:
  3392. IF_DEBUG( ISAPI_ERROR_RETURNS )
  3393. {
  3394. DBGPRINTF(( DBG_CONTEXT,
  3395. "\r\n"
  3396. " HSE_REQ_ADD_FRAGMENT_TO_CACHE[%p]: Parameter validation failure\r\n"
  3397. " Unknown element type: %d\r\n"
  3398. " Fragment Name: '%s'\r\n"
  3399. " <END>\r\n\r\n",
  3400. pIsapiContext,
  3401. pHseVectorElement->ElementType ));
  3402. }
  3403. return HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER);
  3404. }
  3405. hr = pIsapiCore->AddFragmentToCache(&VectorElement,
  3406. pszFragmentName);
  3407. if ( FAILED( hr ) )
  3408. {
  3409. IF_DEBUG( ISAPI_ERROR_RETURNS )
  3410. {
  3411. DBGPRINTF(( DBG_CONTEXT,
  3412. "\r\n"
  3413. " HSE_REQ_ADD_FRAGMENT_TO_CACHE[%p]: Failed\r\n"
  3414. " Error: 0x%08x\r\n"
  3415. " <END>\r\n\r\n",
  3416. pIsapiContext,
  3417. hr ));
  3418. }
  3419. return hr;
  3420. }
  3421. return hr;
  3422. }
  3423. HRESULT
  3424. SSFReadFragmentFromCache(
  3425. ISAPI_CONTEXT * pIsapiContext,
  3426. WCHAR * pszFragmentName,
  3427. BYTE * pvBuffer,
  3428. DWORD * pcbSize
  3429. )
  3430. /*++
  3431. Routine Description:
  3432. Read the given fragment from the fragment-cache
  3433. Arguments:
  3434. pIsapiContext - The ISAPI_CONTEXT associated with this command.
  3435. pszFragmentName - The name of the fragment
  3436. pvBuffer - The buffer to read the fragment in
  3437. pcbSize - On entry, the size of the buffer and on exit, the number of bytes copied
  3438. Return Value:
  3439. HRESULT
  3440. --*/
  3441. {
  3442. IIsapiCore *pIsapiCore = pIsapiContext->QueryIsapiCoreInterface();
  3443. HRESULT hr;
  3444. IF_DEBUG( ISAPI_SSF_DETAILS )
  3445. {
  3446. DBGPRINTF(( DBG_CONTEXT,
  3447. "\r\n"
  3448. " HSE_REQ_READ_FRAGMENT_FROM_CACHE[%p]: Function Entry\r\n"
  3449. " Fragment Name: '%S'\r\n"
  3450. " <END>\r\n\r\n",
  3451. pIsapiContext,
  3452. pszFragmentName ));
  3453. }
  3454. if ( pIsapiCore == NULL )
  3455. {
  3456. IF_DEBUG( ISAPI_ERROR_RETURNS )
  3457. {
  3458. DBGPRINTF(( DBG_CONTEXT,
  3459. "\r\n"
  3460. " HSE_REQ_READ_FRAGMENT_FROM_CACHE[%p]: Failed to get interface to server core\r\n"
  3461. " <END>\r\n\r\n",
  3462. pIsapiContext ));
  3463. }
  3464. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  3465. }
  3466. //
  3467. // verify the data passed in
  3468. //
  3469. if ( pszFragmentName == NULL ||
  3470. pcbSize == NULL ||
  3471. (pvBuffer == NULL && *pcbSize != 0 ) )
  3472. {
  3473. IF_DEBUG( ISAPI_ERROR_RETURNS )
  3474. {
  3475. DBGPRINTF(( DBG_CONTEXT,
  3476. "\r\n"
  3477. " HSE_REQ_READ_FRAGMENT_FROM_CACHE[%p]: Parameter validation failure\r\n"
  3478. " Fragment Name: '%s'\r\n"
  3479. " Size Ptr: %p\r\n"
  3480. " Size: %d\r\n"
  3481. " Buffer Ptr: %p\r\n"
  3482. " <END>\r\n\r\n",
  3483. pIsapiContext,
  3484. pszFragmentName,
  3485. pcbSize,
  3486. pcbSize ? *pcbSize : 0,
  3487. pvBuffer ));
  3488. }
  3489. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  3490. }
  3491. hr = pIsapiCore->ReadFragmentFromCache(pszFragmentName,
  3492. pvBuffer,
  3493. *pcbSize,
  3494. pcbSize);
  3495. if ( FAILED( hr ) )
  3496. {
  3497. IF_DEBUG( ISAPI_ERROR_RETURNS )
  3498. {
  3499. DBGPRINTF(( DBG_CONTEXT,
  3500. "\r\n"
  3501. " HSE_REQ_READ_FRAGMENT_FROM_CACHE[%p]: Failed\r\n"
  3502. " Error: 0x%08x\r\n"
  3503. " <END>\r\n\r\n",
  3504. pIsapiContext,
  3505. hr ));
  3506. }
  3507. return hr;
  3508. }
  3509. return hr;
  3510. }
  3511. HRESULT
  3512. SSFRemoveFragmentFromCache(
  3513. ISAPI_CONTEXT * pIsapiContext,
  3514. WCHAR * pszFragmentName
  3515. )
  3516. /*++
  3517. Routine Description:
  3518. Remove the given fragment from the fragment-cache
  3519. Arguments:
  3520. pIsapiContext - The ISAPI_CONTEXT associated with this command.
  3521. pszFragmentName - The name of the fragment
  3522. Return Value:
  3523. HRESULT
  3524. --*/
  3525. {
  3526. IIsapiCore *pIsapiCore = pIsapiContext->QueryIsapiCoreInterface();
  3527. HRESULT hr;
  3528. IF_DEBUG( ISAPI_SSF_DETAILS )
  3529. {
  3530. DBGPRINTF(( DBG_CONTEXT,
  3531. "\r\n"
  3532. " HSE_REQ_REMOVE_FRAGMENT_FROM_CACHE[%p]: Function Entry\r\n"
  3533. " Fragment Name: '%S'\r\n"
  3534. " <END>\r\n\r\n",
  3535. pIsapiContext,
  3536. pszFragmentName ));
  3537. }
  3538. if ( pIsapiCore == NULL )
  3539. {
  3540. IF_DEBUG( ISAPI_ERROR_RETURNS )
  3541. {
  3542. DBGPRINTF(( DBG_CONTEXT,
  3543. "\r\n"
  3544. " HSE_REQ_REMOVE_FRAGMENT_FROM_CACHE[%p]: Failed to get interface to server core\r\n"
  3545. " <END>\r\n\r\n",
  3546. pIsapiContext ));
  3547. }
  3548. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  3549. }
  3550. //
  3551. // verify the data passed in
  3552. //
  3553. if ( pszFragmentName == NULL )
  3554. {
  3555. IF_DEBUG( ISAPI_ERROR_RETURNS )
  3556. {
  3557. DBGPRINTF(( DBG_CONTEXT,
  3558. "\r\n"
  3559. " HSE_REQ_REMOVE_FRAGMENT_FROM_CACHE[%p]: Parameter validation failure\r\n"
  3560. " Fragment Name: '%s'\r\n"
  3561. " <END>\r\n\r\n",
  3562. pIsapiContext,
  3563. pszFragmentName ));
  3564. }
  3565. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  3566. }
  3567. hr = pIsapiCore->RemoveFragmentFromCache(pszFragmentName);
  3568. if ( FAILED( hr ) )
  3569. {
  3570. IF_DEBUG( ISAPI_ERROR_RETURNS )
  3571. {
  3572. DBGPRINTF(( DBG_CONTEXT,
  3573. "\r\n"
  3574. " HSE_REQ_REMOVE_FRAGMENT_FROM_CACHE[%p]: Failed\r\n"
  3575. " Error: 0x%08x\r\n"
  3576. " <END>\r\n\r\n",
  3577. pIsapiContext,
  3578. hr ));
  3579. }
  3580. return hr;
  3581. }
  3582. return hr;
  3583. }
  3584. HRESULT
  3585. SSFGetMetadataProperty(
  3586. ISAPI_CONTEXT * pIsapiContext,
  3587. DWORD_PTR dwPropertyId,
  3588. BYTE * pbBuffer,
  3589. DWORD * pcbBuffer
  3590. )
  3591. /*++
  3592. Routine Description:
  3593. Retrieve a property from the UT_FILE metadata associated with the URL
  3594. of this request
  3595. Arguments:
  3596. pIsapiContext - ISAPI_CONTEXT
  3597. dwPropertyId - MD_* metabase property ID
  3598. pbBuffer - Points to buffer
  3599. pcbBuffer - On input size of buffer, on output size needed/used
  3600. Return Value:
  3601. HRESULT
  3602. --*/
  3603. {
  3604. IIsapiCore * pIsapiCore;
  3605. HRESULT hr;
  3606. METADATA_RECORD * pRecord;
  3607. DBG_ASSERT( pIsapiContext != NULL );
  3608. IF_DEBUG( ISAPI_SSF_DETAILS )
  3609. {
  3610. DBGPRINTF(( DBG_CONTEXT,
  3611. "\r\n"
  3612. " HSE_REQ_GET_METADATA_PROPERTY[%p]: Function Entry\r\n"
  3613. " PropertyID: 0x%08x (%d)\r\n"
  3614. " <END>\r\n\r\n",
  3615. pIsapiContext,
  3616. dwPropertyId,
  3617. dwPropertyId ));
  3618. }
  3619. pIsapiCore = pIsapiContext->QueryIsapiCoreInterface();
  3620. DBG_ASSERT( pIsapiCore != NULL );
  3621. if ( pcbBuffer == NULL )
  3622. {
  3623. IF_DEBUG( ISAPI_ERROR_RETURNS )
  3624. {
  3625. DBGPRINTF(( DBG_CONTEXT,
  3626. "\r\n"
  3627. " HSE_REQ_GET_METADATA_PROPERTY[%p]: Parameter validation failure\r\n"
  3628. " Buffer Ptr: NULL\r\n"
  3629. " <END>\r\n\r\n",
  3630. pIsapiContext ));
  3631. }
  3632. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  3633. }
  3634. hr = pIsapiCore->GetMetadataProperty( (DWORD) dwPropertyId,
  3635. pbBuffer,
  3636. *pcbBuffer,
  3637. pcbBuffer );
  3638. if ( FAILED( hr ) )
  3639. {
  3640. IF_DEBUG( ISAPI_ERROR_RETURNS )
  3641. {
  3642. DBGPRINTF(( DBG_CONTEXT,
  3643. "\r\n"
  3644. " HSE_REQ_GET_METADATA_PROPERTY[%p]: Failed\r\n"
  3645. " Error: 0x%08x\r\n"
  3646. " <END>\r\n\r\n",
  3647. pIsapiContext,
  3648. hr ));
  3649. }
  3650. return hr;
  3651. }
  3652. else
  3653. {
  3654. //
  3655. // OK. Before we return the METADATA_RECORD back to caller, set the
  3656. // pbMDData buffer pointer (since for OOP the pointer can only be
  3657. // calculated on this side
  3658. //
  3659. DBG_ASSERT( *pcbBuffer >= sizeof( METADATA_RECORD ) );
  3660. pRecord = (METADATA_RECORD*) pbBuffer;
  3661. pRecord->pbMDData = (BYTE*) (pRecord + 1);
  3662. }
  3663. return hr;
  3664. }
  3665. HRESULT
  3666. SSFGetCacheInvalidationCallback(
  3667. ISAPI_CONTEXT * pIsapiContext,
  3668. PFN_HSE_CACHE_INVALIDATION_CALLBACK * pfnCallback
  3669. )
  3670. /*++
  3671. Routine description:
  3672. Get the callback function to use to flush a response from the http.sys cache
  3673. Arguments:
  3674. pIsapiContext - The ISAPI_CONTEXT corresponding to the request
  3675. pfnCallback - On successful return, the address of the callback function
  3676. Return:
  3677. HRESULT
  3678. --*/
  3679. {
  3680. IIsapiCore * pIsapiCore;
  3681. HRESULT hr;
  3682. DBG_ASSERT( pIsapiContext != NULL );
  3683. IF_DEBUG( ISAPI_SSF_DETAILS )
  3684. {
  3685. DBGPRINTF(( DBG_CONTEXT,
  3686. "\r\n"
  3687. " HSE_REQ_GET_CACHE_INVALIDATION_CALLBACK[%p]: Function Entry\r\n"
  3688. " <END>\r\n\r\n",
  3689. pIsapiContext ));
  3690. }
  3691. pIsapiCore = pIsapiContext->QueryIsapiCoreInterface();
  3692. DBG_ASSERT( pIsapiCore != NULL );
  3693. if ( pfnCallback == NULL )
  3694. {
  3695. IF_DEBUG( ISAPI_ERROR_RETURNS )
  3696. {
  3697. DBGPRINTF(( DBG_CONTEXT,
  3698. "\r\n"
  3699. " HSE_REQ_GET_CACHE_INVALIDATION_CALLBACK[%p]: Parameter validation failure\r\n"
  3700. " Callback Ptr: NULL\r\n"
  3701. " <END>\r\n\r\n",
  3702. pIsapiContext ));
  3703. }
  3704. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  3705. }
  3706. hr = pIsapiCore->GetCacheInvalidationCallback((DWORD64 *)pfnCallback);
  3707. if ( FAILED( hr ) )
  3708. {
  3709. IF_DEBUG( ISAPI_ERROR_RETURNS )
  3710. {
  3711. DBGPRINTF(( DBG_CONTEXT,
  3712. "\r\n"
  3713. " HSE_REQ_GET_CACHE_INVALIDATION_CALLBACK[%p]: Failed\r\n"
  3714. " Error: 0x%08x\r\n"
  3715. " <END>\r\n\r\n",
  3716. pIsapiContext,
  3717. hr ));
  3718. }
  3719. return hr;
  3720. }
  3721. return hr;
  3722. }
  3723. HRESULT
  3724. SSFCloseConnection(
  3725. ISAPI_CONTEXT * pIsapiContext
  3726. )
  3727. {
  3728. IIsapiCore * pIsapiCore;
  3729. HRESULT hr;
  3730. DBG_ASSERT( pIsapiContext );
  3731. DBG_ASSERT( pIsapiContext->CheckSignature() );
  3732. DBG_REQUIRE( ( pIsapiCore = pIsapiContext->QueryIsapiCoreInterface() ) != NULL );
  3733. IF_DEBUG( ISAPI_SSF_DETAILS )
  3734. {
  3735. DBGPRINTF(( DBG_CONTEXT,
  3736. "\r\n"
  3737. " HSE_REQ_CLOSE_CONNECTION[%p]: Function Entry\r\n"
  3738. " <END>\r\n\r\n",
  3739. pIsapiContext ));
  3740. }
  3741. hr = pIsapiCore->CloseConnection();
  3742. if ( FAILED( hr ) )
  3743. {
  3744. IF_DEBUG( ISAPI_ERROR_RETURNS )
  3745. {
  3746. DBGPRINTF(( DBG_CONTEXT,
  3747. "\r\n"
  3748. " HSE_REQ_CLOSE_CONNECTION[%p]: Failed\r\n"
  3749. " Error: 0x%08x\r\n"
  3750. " <END>\r\n\r\n",
  3751. pIsapiContext,
  3752. hr ));
  3753. }
  3754. return hr;
  3755. }
  3756. return hr;
  3757. }
  3758. // stristr (stolen from fts.c, wickn)
  3759. //
  3760. // case-insensitive version of strstr.
  3761. // stristr returns a pointer to the first occurrence of
  3762. // pszSubString in pszString. The search does not include
  3763. // terminating nul characters.
  3764. //
  3765. // BUGBUG: is this DBCS-safe?
  3766. const char*
  3767. stristr2(
  3768. const char* pszString,
  3769. const char* pszSubString
  3770. )
  3771. {
  3772. const char *cp1 = (const char*) pszString, *cp2, *cp1a;
  3773. char first;
  3774. // get the first char in string to find
  3775. first = pszSubString[0];
  3776. // first char often won't be alpha
  3777. if (isalpha(first))
  3778. {
  3779. first = (char) tolower(first);
  3780. for ( ; *cp1 != '\0'; cp1++)
  3781. {
  3782. if (tolower(*cp1) == first)
  3783. {
  3784. for (cp1a = &cp1[1], cp2 = (const char*) &pszSubString[1];
  3785. ;
  3786. cp1a++, cp2++)
  3787. {
  3788. if (*cp2 == '\0')
  3789. return cp1;
  3790. if (tolower(*cp1a) != tolower(*cp2))
  3791. break;
  3792. }
  3793. }
  3794. }
  3795. }
  3796. else
  3797. {
  3798. for ( ; *cp1 != '\0' ; cp1++)
  3799. {
  3800. if (*cp1 == first)
  3801. {
  3802. for (cp1a = &cp1[1], cp2 = (const char*) &pszSubString[1];
  3803. ;
  3804. cp1a++, cp2++)
  3805. {
  3806. if (*cp2 == '\0')
  3807. return cp1;
  3808. if (tolower(*cp1a) != tolower(*cp2))
  3809. break;
  3810. }
  3811. }
  3812. }
  3813. }
  3814. return NULL;
  3815. }