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

4401 lines
101 KiB

  1. /*++
  2. Copyright (c) 1998-2001 Microsoft Corporation
  3. Module Name:
  4. ioctl.cxx
  5. Abstract:
  6. This module implements various IOCTL handlers.
  7. Author:
  8. Keith Moore (keithmo) 10-Jun-1998
  9. Revision History:
  10. Paul McDaniel (paulmcd) 15-Mar-1999 Modified SendResponse
  11. --*/
  12. #include "precomp.h"
  13. #define VALIDATE_OFFSET( off, input ) ((off) < (input))
  14. #define VALIDATE_LENGTH( len, input ) ((len) < (input))
  15. #define VALIDATE_OFFSET_LENGTH_PAIR( off, len, input ) \
  16. ( VALIDATE_OFFSET( off, input ) && \
  17. VALIDATE_LENGTH( len, input ) && \
  18. (((off) + (len)) < (input)) )
  19. VOID
  20. UlpRestartSendHttpResponse(
  21. IN PVOID pCompletionContext,
  22. IN NTSTATUS Status,
  23. IN ULONG_PTR Information
  24. );
  25. #ifdef ALLOC_PRAGMA
  26. #pragma alloc_text( PAGE, UlQueryControlChannelIoctl )
  27. #pragma alloc_text( PAGE, UlSetControlChannelIoctl )
  28. #pragma alloc_text( PAGE, UlCreateConfigGroupIoctl )
  29. #pragma alloc_text( PAGE, UlDeleteConfigGroupIoctl )
  30. #pragma alloc_text( PAGE, UlQueryConfigGroupIoctl )
  31. #pragma alloc_text( PAGE, UlSetConfigGroupIoctl )
  32. #pragma alloc_text( PAGE, UlAddUrlToConfigGroupIoctl )
  33. #pragma alloc_text( PAGE, UlRemoveUrlFromConfigGroupIoctl )
  34. #pragma alloc_text( PAGE, UlRemoveAllUrlsFromConfigGroupIoctl )
  35. #pragma alloc_text( PAGE, UlConfigGroupControlIoctl )
  36. #pragma alloc_text( PAGE, UlQueryAppPoolInformationIoctl )
  37. #pragma alloc_text( PAGE, UlSetAppPoolInformationIoctl )
  38. #pragma alloc_text( PAGE, UlReceiveHttpRequestIoctl )
  39. #pragma alloc_text( PAGE, UlReceiveEntityBodyIoctl )
  40. #pragma alloc_text( PAGE, UlSendHttpResponseIoctl )
  41. #pragma alloc_text( PAGE, UlSendEntityBodyIoctl )
  42. #pragma alloc_text( PAGE, UlFlushResponseCacheIoctl )
  43. #pragma alloc_text( PAGE, UlWaitForDemandStartIoctl )
  44. #pragma alloc_text( PAGE, UlWaitForDisconnectIoctl )
  45. #pragma alloc_text( PAGE, UlAddTransientUrlIoctl )
  46. #pragma alloc_text( PAGE, UlRemoveTransientUrlIoctl )
  47. #pragma alloc_text( PAGE, UlFilterAcceptIoctl )
  48. #pragma alloc_text( PAGE, UlFilterCloseIoctl )
  49. #pragma alloc_text( PAGE, UlFilterRawReadIoctl )
  50. #pragma alloc_text( PAGE, UlFilterRawWriteIoctl )
  51. #pragma alloc_text( PAGE, UlFilterAppReadIoctl )
  52. #pragma alloc_text( PAGE, UlFilterAppWriteIoctl )
  53. #pragma alloc_text( PAGE, UlReceiveClientCertIoctl )
  54. #pragma alloc_text( PAGE, UlGetCountersIoctl )
  55. #endif // ALLOC_PRAGMA
  56. #if 0
  57. NOT PAGEABLE -- UlpRestartSendHttpResponse
  58. #endif
  59. //
  60. // Public functions.
  61. //
  62. /***************************************************************************++
  63. Routine Description:
  64. This routine queries information associated with a control channel.
  65. Note: This is a METHOD_OUT_DIRECT IOCTL.
  66. Arguments:
  67. pIrp - Supplies a pointer to the IO request packet.
  68. pIrpSp - Supplies a pointer to the IO stack location to use for this
  69. request.
  70. Return Value:
  71. NTSTATUS - Completion status.
  72. --***************************************************************************/
  73. NTSTATUS
  74. UlQueryControlChannelIoctl(
  75. IN PIRP pIrp,
  76. IN PIO_STACK_LOCATION pIrpSp
  77. )
  78. {
  79. NTSTATUS Status;
  80. PHTTP_CONTROL_CHANNEL_INFO pInfo = NULL;
  81. PUL_CONTROL_CHANNEL pControlChannel;
  82. PVOID pMdlBuffer;
  83. ULONG length;
  84. PVOID pMdlVa;
  85. //
  86. // sanity check.
  87. //
  88. PAGED_CODE();
  89. //
  90. // better be a control channel
  91. //
  92. if (IS_CONTROL_CHANNEL(pIrpSp->FileObject) == FALSE)
  93. {
  94. //
  95. // Not a control channel.
  96. //
  97. Status = STATUS_INVALID_DEVICE_REQUEST;
  98. goto end;
  99. }
  100. pControlChannel = GET_CONTROL_CHANNEL(pIrpSp->FileObject);
  101. if (IS_VALID_CONTROL_CHANNEL(pControlChannel) == FALSE)
  102. {
  103. Status = STATUS_INVALID_PARAMETER;
  104. goto end;
  105. }
  106. //
  107. // Ensure the input buffer looks good
  108. //
  109. if (pIrpSp->Parameters.DeviceIoControl.InputBufferLength <
  110. sizeof(HTTP_CONTROL_CHANNEL_INFO))
  111. {
  112. //
  113. // input buffer too small.
  114. //
  115. Status = STATUS_BUFFER_TOO_SMALL;
  116. goto end;
  117. }
  118. //
  119. // fetch it
  120. //
  121. pInfo = (PHTTP_CONTROL_CHANNEL_INFO)pIrp->AssociatedIrp.SystemBuffer;
  122. ASSERT(pInfo != NULL);
  123. __try
  124. {
  125. switch (pInfo->InformationClass)
  126. {
  127. case HttpControlChannelStateInformation:
  128. case HttpControlChannelBandwidthInformation:
  129. case HttpControlChannelConnectionInformation:
  130. case HttpControlChannelAutoResponseInformation:
  131. // if no outbut buffer pass down in the Irp
  132. // that means app is asking for the required
  133. // field length
  134. if (!pIrp->MdlAddress)
  135. {
  136. pMdlBuffer = NULL;
  137. }
  138. else
  139. {
  140. pMdlBuffer = MmGetSystemAddressForMdlSafe(
  141. pIrp->MdlAddress,
  142. LowPagePriority
  143. );
  144. if (pMdlBuffer == NULL)
  145. {
  146. Status = STATUS_INSUFFICIENT_RESOURCES;
  147. __leave;
  148. }
  149. // Also make sure that user buffer was good
  150. pMdlVa = MmGetMdlVirtualAddress(pIrp->MdlAddress);
  151. ProbeForWrite( pMdlVa,
  152. pIrpSp->Parameters.DeviceIoControl.OutputBufferLength,
  153. sizeof(UCHAR) );
  154. }
  155. Status = UlGetControlChannelInformation(
  156. pControlChannel,
  157. pInfo->InformationClass,
  158. pMdlBuffer,
  159. pIrpSp->Parameters.DeviceIoControl.OutputBufferLength,
  160. &length
  161. );
  162. if (!NT_SUCCESS(Status))
  163. {
  164. __leave;
  165. }
  166. pIrp->IoStatus.Information = (ULONG_PTR)length;
  167. break;
  168. default:
  169. Status = STATUS_INVALID_PARAMETER;
  170. __leave;
  171. break;
  172. }
  173. }
  174. __except( UL_EXCEPTION_FILTER() )
  175. {
  176. Status = UL_CONVERT_EXCEPTION_CODE(GetExceptionCode());
  177. }
  178. end:
  179. //
  180. // complete the request.
  181. //
  182. if (Status != STATUS_PENDING)
  183. {
  184. pIrp->IoStatus.Status = Status;
  185. UlCompleteRequest( pIrp, g_UlPriorityBoost );
  186. }
  187. RETURN( Status );
  188. } // UlQueryControlChannelIoctl
  189. /***************************************************************************++
  190. Routine Description:
  191. This routine sets information associated with a control channel.
  192. Note: This is a METHOD_IN_DIRECT IOCTL.
  193. Arguments:
  194. pIrp - Supplies a pointer to the IO request packet.
  195. pIrpSp - Supplies a pointer to the IO stack location to use for this
  196. request.
  197. Return Value:
  198. NTSTATUS - Completion status.
  199. --***************************************************************************/
  200. NTSTATUS
  201. UlSetControlChannelIoctl(
  202. IN PIRP pIrp,
  203. IN PIO_STACK_LOCATION pIrpSp
  204. )
  205. {
  206. NTSTATUS Status;
  207. PHTTP_CONTROL_CHANNEL_INFO pInfo;
  208. PUL_CONTROL_CHANNEL pControlChannel;
  209. PVOID pMdlBuffer;
  210. //
  211. // sanity check.
  212. //
  213. PAGED_CODE();
  214. //
  215. // better be a control channel
  216. //
  217. if (IS_CONTROL_CHANNEL(pIrpSp->FileObject) == FALSE)
  218. {
  219. //
  220. // Not a control channel.
  221. //
  222. Status = STATUS_INVALID_DEVICE_REQUEST;
  223. goto end;
  224. }
  225. pControlChannel = GET_CONTROL_CHANNEL(pIrpSp->FileObject);
  226. if (IS_VALID_CONTROL_CHANNEL(pControlChannel) == FALSE)
  227. {
  228. Status = STATUS_INVALID_PARAMETER;
  229. goto end;
  230. }
  231. //
  232. // Ensure the input buffer looks good
  233. //
  234. if (pIrpSp->Parameters.DeviceIoControl.InputBufferLength <
  235. sizeof(HTTP_CONTROL_CHANNEL_INFO))
  236. {
  237. //
  238. // input buffer too small.
  239. //
  240. Status = STATUS_BUFFER_TOO_SMALL;
  241. goto end;
  242. }
  243. //
  244. //
  245. // Ensure the output buffer looks good
  246. //
  247. if (!pIrp->MdlAddress)
  248. {
  249. Status = STATUS_INVALID_PARAMETER;
  250. goto end;
  251. }
  252. // fetch it
  253. //
  254. pInfo = (PHTTP_CONTROL_CHANNEL_INFO)pIrp->AssociatedIrp.SystemBuffer;
  255. ASSERT(pInfo != NULL);
  256. switch (pInfo->InformationClass)
  257. {
  258. case HttpControlChannelStateInformation:
  259. case HttpControlChannelBandwidthInformation:
  260. case HttpControlChannelConnectionInformation:
  261. case HttpControlChannelAutoResponseInformation:
  262. case HttpControlChannelFilterInformation:
  263. case HttpControlChannelTimeoutInformation:
  264. case HttpControlChannelUTF8Logging:
  265. //
  266. // call the function
  267. //
  268. pMdlBuffer = MmGetSystemAddressForMdlSafe(
  269. pIrp->MdlAddress,
  270. LowPagePriority
  271. );
  272. if (pMdlBuffer == NULL)
  273. {
  274. Status = STATUS_INSUFFICIENT_RESOURCES;
  275. }
  276. else
  277. {
  278. Status = UlSetControlChannelInformation(
  279. pControlChannel,
  280. pInfo->InformationClass,
  281. pMdlBuffer,
  282. pIrpSp->Parameters.DeviceIoControl.OutputBufferLength
  283. );
  284. }
  285. if (NT_SUCCESS(Status) == FALSE)
  286. goto end;
  287. break;
  288. default:
  289. Status = STATUS_INVALID_PARAMETER;
  290. goto end;
  291. }
  292. end:
  293. //
  294. // complete the request.
  295. //
  296. if (Status != STATUS_PENDING)
  297. {
  298. pIrp->IoStatus.Status = Status;
  299. UlCompleteRequest( pIrp, g_UlPriorityBoost );
  300. }
  301. RETURN( Status );
  302. } // UlSetControlChannelIoctl
  303. /***************************************************************************++
  304. Routine Description:
  305. This routine creates a new configuration group.
  306. Note: This is a METHOD_BUFFERED IOCTL.
  307. Arguments:
  308. pIrp - Supplies a pointer to the IO request packet.
  309. pIrpSp - Supplies a pointer to the IO stack location to use for this
  310. request.
  311. Return Value:
  312. NTSTATUS - Completion status.
  313. --***************************************************************************/
  314. NTSTATUS
  315. UlCreateConfigGroupIoctl(
  316. IN PIRP pIrp,
  317. IN PIO_STACK_LOCATION pIrpSp
  318. )
  319. {
  320. NTSTATUS Status;
  321. PHTTP_CONFIG_GROUP_INFO pInfo = NULL;
  322. //
  323. // sanity check.
  324. //
  325. PAGED_CODE();
  326. // better be a control channel
  327. //
  328. if (IS_CONTROL_CHANNEL(pIrpSp->FileObject) == FALSE)
  329. {
  330. // Not a control channel.
  331. //
  332. Status = STATUS_INVALID_DEVICE_REQUEST;
  333. goto end;
  334. }
  335. // Ensure the output buffer is large enough.
  336. //
  337. if (pIrpSp->Parameters.DeviceIoControl.OutputBufferLength <
  338. sizeof(HTTP_CONFIG_GROUP_INFO))
  339. {
  340. // output buffer too small.
  341. Status = STATUS_BUFFER_TOO_SMALL;
  342. goto end;
  343. }
  344. // Fetch out the output buffer
  345. //
  346. pInfo = (PHTTP_CONFIG_GROUP_INFO)pIrp->AssociatedIrp.SystemBuffer;
  347. ASSERT(pInfo != NULL);
  348. // it's pure output, wipe it to be sure
  349. //
  350. RtlZeroMemory(pInfo, sizeof(HTTP_CONFIG_GROUP_INFO));
  351. // Call the internal worker func
  352. //
  353. Status = UlCreateConfigGroup(
  354. GET_CONTROL_CHANNEL(pIrpSp->FileObject),
  355. &pInfo->ConfigGroupId
  356. );
  357. if (NT_SUCCESS(Status) == FALSE)
  358. goto end;
  359. end:
  360. // complete the request.
  361. //
  362. if (Status != STATUS_PENDING)
  363. {
  364. pIrp->IoStatus.Status = Status;
  365. // how much output should we return?
  366. //
  367. pIrp->IoStatus.Information = sizeof(HTTP_CONFIG_GROUP_INFO);
  368. UlCompleteRequest( pIrp, g_UlPriorityBoost );
  369. }
  370. RETURN( Status );
  371. } // UlCreateConfigGroupIoctl
  372. /***************************************************************************++
  373. Routine Description:
  374. This routine deletes an existing configuration group.
  375. Note: This is a METHOD_BUFFERED IOCTL.
  376. Arguments:
  377. pIrp - Supplies a pointer to the IO request packet.
  378. pIrpSp - Supplies a pointer to the IO stack location to use for this
  379. request.
  380. Return Value:
  381. NTSTATUS - Completion status.
  382. --***************************************************************************/
  383. NTSTATUS
  384. UlDeleteConfigGroupIoctl(
  385. IN PIRP pIrp,
  386. IN PIO_STACK_LOCATION pIrpSp
  387. )
  388. {
  389. NTSTATUS Status;
  390. PHTTP_CONFIG_GROUP_INFO pInfo = NULL;
  391. //
  392. // sanity check.
  393. //
  394. PAGED_CODE();
  395. // better be a control channel
  396. //
  397. if (IS_CONTROL_CHANNEL(pIrpSp->FileObject) == FALSE)
  398. {
  399. // Not a control channel.
  400. //
  401. Status = STATUS_INVALID_DEVICE_REQUEST;
  402. goto end;
  403. }
  404. // Ensure the input buffer is large enough.
  405. //
  406. if (pIrpSp->Parameters.DeviceIoControl.InputBufferLength <
  407. sizeof(HTTP_CONFIG_GROUP_INFO))
  408. {
  409. // output buffer too small.
  410. Status = STATUS_BUFFER_TOO_SMALL;
  411. goto end;
  412. }
  413. // fetch out the input buffer
  414. //
  415. pInfo = (PHTTP_CONFIG_GROUP_INFO)pIrp->AssociatedIrp.SystemBuffer;
  416. ASSERT(pInfo != NULL);
  417. // Call the internal worker func
  418. //
  419. __try
  420. {
  421. HTTP_CONFIG_GROUP_ID ConfigGroupId = pInfo->ConfigGroupId;
  422. Status = UlDeleteConfigGroup(ConfigGroupId);
  423. }
  424. __except( UL_EXCEPTION_FILTER() )
  425. {
  426. Status = UL_CONVERT_EXCEPTION_CODE(GetExceptionCode());
  427. }
  428. if (NT_SUCCESS(Status) == FALSE)
  429. goto end;
  430. end:
  431. // complete the request.
  432. //
  433. if (Status != STATUS_PENDING)
  434. {
  435. pIrp->IoStatus.Status = Status;
  436. UlCompleteRequest( pIrp, g_UlPriorityBoost );
  437. }
  438. RETURN( Status );
  439. } // UlDeleteConfigGroupIoctl
  440. /***************************************************************************++
  441. Routine Description:
  442. This routine queries information associated with a configuration group.
  443. Note: This is a METHOD_OUT_DIRECT IOCTL.
  444. Arguments:
  445. pIrp - Supplies a pointer to the IO request packet.
  446. pIrpSp - Supplies a pointer to the IO stack location to use for this
  447. request.
  448. Return Value:
  449. NTSTATUS - Completion status.
  450. --***************************************************************************/
  451. NTSTATUS
  452. UlQueryConfigGroupIoctl(
  453. IN PIRP pIrp,
  454. IN PIO_STACK_LOCATION pIrpSp
  455. )
  456. {
  457. NTSTATUS Status;
  458. PHTTP_CONFIG_GROUP_INFO pInfo = NULL;
  459. PVOID pMdlBuffer;
  460. ULONG length = 0L;
  461. //
  462. // sanity check.
  463. //
  464. PAGED_CODE();
  465. //
  466. // Going to access the url string from user mode memory
  467. //
  468. __try
  469. {
  470. //
  471. // better be a control channel
  472. //
  473. if (IS_CONTROL_CHANNEL(pIrpSp->FileObject) == FALSE)
  474. {
  475. //
  476. // Not a control channel.
  477. //
  478. Status = STATUS_INVALID_DEVICE_REQUEST;
  479. __leave;
  480. }
  481. //
  482. // Ensure the input buffer looks good
  483. //
  484. if (pIrpSp->Parameters.DeviceIoControl.InputBufferLength <
  485. sizeof(HTTP_CONFIG_GROUP_INFO))
  486. {
  487. //
  488. // input buffer too small.
  489. //
  490. Status = STATUS_BUFFER_TOO_SMALL;
  491. __leave;
  492. }
  493. //
  494. // fetch it
  495. //
  496. pInfo = (PHTTP_CONFIG_GROUP_INFO)pIrp->AssociatedIrp.SystemBuffer;
  497. ASSERT(pInfo != NULL);
  498. switch (pInfo->InformationClass)
  499. {
  500. #if DBG
  501. case HttpConfigGroupGetUrlInfo:
  502. {
  503. PHTTP_CONFIG_GROUP_DBG_URL_INFO pUrlInfo;
  504. PUL_URL_CONFIG_GROUP_INFO pUrlCGInfo;
  505. // check the output buffer
  506. //
  507. if (pIrpSp->Parameters.DeviceIoControl.OutputBufferLength <
  508. sizeof(HTTP_CONFIG_GROUP_DBG_URL_INFO))
  509. {
  510. // output buffer too small.
  511. Status = STATUS_BUFFER_TOO_SMALL;
  512. __leave;
  513. }
  514. // grab the buffer
  515. //
  516. pUrlInfo = (PHTTP_CONFIG_GROUP_DBG_URL_INFO)
  517. MmGetSystemAddressForMdlSafe(
  518. pIrp->MdlAddress,
  519. NormalPagePriority
  520. );
  521. if (pUrlInfo == NULL)
  522. {
  523. Status = STATUS_INSUFFICIENT_RESOURCES;
  524. __leave;
  525. }
  526. pUrlCGInfo = (PUL_URL_CONFIG_GROUP_INFO)UL_ALLOCATE_POOL(
  527. NonPagedPool,
  528. sizeof(UL_URL_CONFIG_GROUP_INFO),
  529. UL_CG_URL_INFO_POOL_TAG
  530. );
  531. if (pUrlCGInfo == NULL)
  532. {
  533. Status = STATUS_INSUFFICIENT_RESOURCES;
  534. __leave;
  535. }
  536. // grab the url
  537. //
  538. if (pUrlInfo->Url.Length == 0 ||
  539. pUrlInfo->Url.MaximumLength > pUrlInfo->Url.Length ||
  540. pUrlInfo->Url.Buffer == NULL)
  541. {
  542. // output buffer too small.
  543. Status = STATUS_INVALID_PARAMETER;
  544. __leave;
  545. }
  546. // good memory?
  547. //
  548. ProbeTestForRead(pUrlInfo->Url.Buffer,
  549. pUrlInfo->Url.Length + sizeof(WCHAR),
  550. sizeof(WCHAR));
  551. // must be null terminated
  552. //
  553. if (pUrlInfo->Url.Buffer[pUrlInfo->Url.Length/sizeof(WCHAR)] != UNICODE_NULL)
  554. {
  555. Status = STATUS_INVALID_PARAMETER;
  556. __leave;
  557. }
  558. // CODEWORK: validate the incoming url.
  559. //
  560. // call the function
  561. //
  562. Status = UlGetConfigGroupInfoForUrl(
  563. pUrlInfo->Url.Buffer,
  564. NULL, // PUL_HTTP_CONNECTION
  565. pUrlCGInfo);
  566. if (NT_SUCCESS(Status) == FALSE)
  567. __leave;
  568. // copy it over
  569. //
  570. //pUrlInfo->Url;
  571. pUrlInfo->MaxBandwidth = -1;
  572. if (pUrlCGInfo->pMaxBandwidth != NULL)
  573. {
  574. pUrlInfo->MaxBandwidth =
  575. pUrlCGInfo->pMaxBandwidth->MaxBandwidth.MaxBandwidth;
  576. }
  577. pUrlInfo->MaxConnections = -1;
  578. if (pUrlCGInfo->pMaxConnections != NULL)
  579. {
  580. pUrlInfo->MaxConnections =
  581. pUrlCGInfo->pMaxConnections->MaxConnections.MaxConnections;
  582. }
  583. pUrlInfo->CurrentState = pUrlCGInfo->CurrentState;
  584. pUrlInfo->UrlContext = pUrlCGInfo->UrlContext;
  585. pUrlInfo->pReserved = pUrlCGInfo;
  586. // update the output length
  587. //
  588. pIrp->IoStatus.Information = sizeof(HTTP_CONFIG_GROUP_DBG_URL_INFO);
  589. }
  590. break;
  591. case HttpConfigGroupFreeUrlInfo:
  592. {
  593. PHTTP_CONFIG_GROUP_DBG_URL_INFO pUrlInfo;
  594. // check the output buffer
  595. //
  596. if (pIrpSp->Parameters.DeviceIoControl.OutputBufferLength <
  597. sizeof(HTTP_CONFIG_GROUP_DBG_URL_INFO))
  598. {
  599. // output buffer too small.
  600. Status = STATUS_BUFFER_TOO_SMALL;
  601. __leave;
  602. }
  603. // grab the buffer
  604. //
  605. pUrlInfo = (PHTTP_CONFIG_GROUP_DBG_URL_INFO)
  606. MmGetSystemAddressForMdlSafe(
  607. pIrp->MdlAddress,
  608. NormalPagePriority
  609. );
  610. if (pUrlInfo == NULL)
  611. {
  612. Status = STATUS_INSUFFICIENT_RESOURCES;
  613. __leave;
  614. }
  615. // call the function
  616. //
  617. UlpConfigGroupInfoRelease(
  618. (PUL_URL_CONFIG_GROUP_INFO)(pUrlInfo->pReserved)
  619. );
  620. UL_FREE_POOL(
  621. (PUL_URL_CONFIG_GROUP_INFO)(pUrlInfo->pReserved),
  622. UL_CG_URL_INFO_POOL_TAG
  623. );
  624. // update the output length
  625. //
  626. pIrp->IoStatus.Information = 0;
  627. }
  628. break;
  629. case HttpConfigGroupUrlStaleTest:
  630. {
  631. Status = STATUS_NOT_SUPPORTED;
  632. }
  633. break;
  634. #endif // DBG
  635. case HttpConfigGroupBandwidthInformation:
  636. case HttpConfigGroupConnectionInformation:
  637. case HttpConfigGroupStateInformation:
  638. case HttpConfigGroupConnectionTimeoutInformation:
  639. //
  640. // call the function
  641. //
  642. pMdlBuffer = MmGetSystemAddressForMdlSafe(
  643. pIrp->MdlAddress,
  644. LowPagePriority
  645. );
  646. if (pMdlBuffer == NULL)
  647. {
  648. Status = STATUS_INSUFFICIENT_RESOURCES;
  649. }
  650. else
  651. {
  652. Status = UlQueryConfigGroupInformation(
  653. pInfo->ConfigGroupId,
  654. pInfo->InformationClass,
  655. pMdlBuffer,
  656. pIrpSp->Parameters.DeviceIoControl.OutputBufferLength,
  657. &length
  658. );
  659. }
  660. if (!NT_SUCCESS(Status))
  661. {
  662. __leave;
  663. }
  664. pIrp->IoStatus.Information = (ULONG_PTR)length;
  665. break;
  666. case HttpConfigGroupAutoResponseInformation:
  667. case HttpConfigGroupAppPoolInformation:
  668. case HttpConfigGroupSecurityInformation:
  669. default:
  670. Status = STATUS_INVALID_PARAMETER;
  671. __leave;
  672. }
  673. }
  674. __except( UL_EXCEPTION_FILTER() )
  675. {
  676. Status = UL_CONVERT_EXCEPTION_CODE(GetExceptionCode());
  677. }
  678. //
  679. // complete the request.
  680. //
  681. if (Status != STATUS_PENDING)
  682. {
  683. pIrp->IoStatus.Status = Status;
  684. UlCompleteRequest( pIrp, g_UlPriorityBoost );
  685. }
  686. RETURN( Status );
  687. } // UlQueryConfigGroupIoctl
  688. /***************************************************************************++
  689. Routine Description:
  690. This routine sets information associated with a configuration group.
  691. Note: This is a METHOD_IN_DIRECT IOCTL.
  692. Arguments:
  693. pIrp - Supplies a pointer to the IO request packet.
  694. pIrpSp - Supplies a pointer to the IO stack location to use for this
  695. request.
  696. Return Value:
  697. NTSTATUS - Completion status.
  698. --***************************************************************************/
  699. NTSTATUS
  700. UlSetConfigGroupIoctl(
  701. IN PIRP pIrp,
  702. IN PIO_STACK_LOCATION pIrpSp
  703. )
  704. {
  705. NTSTATUS Status;
  706. PHTTP_CONFIG_GROUP_INFO pInfo = NULL;
  707. PVOID pMdlBuffer;
  708. PVOID pMdlVa;
  709. ULONG OutputLength;
  710. //
  711. // sanity check.
  712. //
  713. PAGED_CODE();
  714. //
  715. // better be a control channel
  716. //
  717. if (IS_CONTROL_CHANNEL(pIrpSp->FileObject) == FALSE)
  718. {
  719. //
  720. // Not a control channel.
  721. //
  722. Status = STATUS_INVALID_DEVICE_REQUEST;
  723. goto end;
  724. }
  725. //
  726. // Ensure the input buffer looks good
  727. //
  728. if (pIrpSp->Parameters.DeviceIoControl.InputBufferLength <
  729. sizeof(HTTP_CONFIG_GROUP_INFO))
  730. {
  731. //
  732. // input buffer too small.
  733. //
  734. Status = STATUS_BUFFER_TOO_SMALL;
  735. goto end;
  736. }
  737. //
  738. // fetch it
  739. //
  740. pInfo = (PHTTP_CONFIG_GROUP_INFO)pIrp->AssociatedIrp.SystemBuffer;
  741. ASSERT(pInfo != NULL);
  742. OutputLength = pIrpSp->Parameters.DeviceIoControl.OutputBufferLength;
  743. switch (pInfo->InformationClass)
  744. {
  745. case HttpConfigGroupLogInformation:
  746. {
  747. __try
  748. {
  749. // if no outbut buffer pass down in the Irp
  750. // that probably means WAS is asking us to
  751. // remove the logging for this config_group
  752. // we will handle this case later...CODEWORK
  753. if (!pIrp->MdlAddress)
  754. {
  755. pMdlBuffer = NULL;
  756. }
  757. else
  758. {
  759. pMdlBuffer = MmGetSystemAddressForMdlSafe(
  760. pIrp->MdlAddress,
  761. LowPagePriority
  762. );
  763. if (pMdlBuffer == NULL)
  764. {
  765. Status = STATUS_INSUFFICIENT_RESOURCES;
  766. __leave;
  767. }
  768. // Also make sure that user buffer was good
  769. pMdlVa = MmGetMdlVirtualAddress(pIrp->MdlAddress);
  770. ProbeTestForRead( pMdlVa,
  771. OutputLength,
  772. sizeof(UCHAR) );
  773. }
  774. UlTrace(IOCTL,
  775. ("UlSetConfigGroupIoctl: CGroupId=%I64x, "
  776. "LogInformation, pMdlBuffer=%p, length=%d\n",
  777. pInfo->ConfigGroupId,
  778. pMdlBuffer,
  779. OutputLength
  780. ));
  781. Status = UlSetConfigGroupInformation(
  782. pInfo->ConfigGroupId,
  783. pInfo->InformationClass,
  784. pMdlBuffer,
  785. OutputLength
  786. );
  787. }
  788. __except( UL_EXCEPTION_FILTER() )
  789. {
  790. Status = UL_CONVERT_EXCEPTION_CODE(GetExceptionCode());
  791. }
  792. if (NT_SUCCESS(Status) == FALSE)
  793. goto end;
  794. }
  795. break;
  796. case HttpConfigGroupAutoResponseInformation:
  797. case HttpConfigGroupAppPoolInformation:
  798. case HttpConfigGroupBandwidthInformation:
  799. case HttpConfigGroupConnectionInformation:
  800. case HttpConfigGroupStateInformation:
  801. case HttpConfigGroupSecurityInformation:
  802. case HttpConfigGroupSiteInformation:
  803. case HttpConfigGroupConnectionTimeoutInformation:
  804. //
  805. // call the function
  806. //
  807. pMdlBuffer = MmGetSystemAddressForMdlSafe(
  808. pIrp->MdlAddress,
  809. LowPagePriority
  810. );
  811. if (pMdlBuffer == NULL)
  812. {
  813. Status = STATUS_INSUFFICIENT_RESOURCES;
  814. }
  815. else
  816. {
  817. UlTrace(IOCTL,
  818. ("UlSetConfigGroupIoctl: CGroupId=%I64x, "
  819. "InfoClass=%d, pMdlBuffer=%p, length=%d\n",
  820. pInfo->ConfigGroupId,
  821. pInfo->InformationClass,
  822. pMdlBuffer,
  823. OutputLength
  824. ));
  825. Status = UlSetConfigGroupInformation(
  826. pInfo->ConfigGroupId,
  827. pInfo->InformationClass,
  828. pMdlBuffer,
  829. OutputLength
  830. );
  831. }
  832. if (NT_SUCCESS(Status) == FALSE)
  833. goto end;
  834. break;
  835. default:
  836. Status = STATUS_INVALID_PARAMETER;
  837. goto end;
  838. break;
  839. }
  840. end:
  841. //
  842. // complete the request.
  843. //
  844. if (Status != STATUS_PENDING)
  845. {
  846. pIrp->IoStatus.Status = Status;
  847. UlCompleteRequest( pIrp, g_UlPriorityBoost );
  848. }
  849. RETURN( Status );
  850. } // UlSetConfigGroupIoctl
  851. /***************************************************************************++
  852. Routine Description:
  853. This routine adds a new URL prefix to a configuration group.
  854. Note: This is a METHOD_BUFFERED IOCTL.
  855. Arguments:
  856. pIrp - Supplies a pointer to the IO request packet.
  857. pIrpSp - Supplies a pointer to the IO stack location to use for this
  858. request.
  859. Return Value:
  860. NTSTATUS - Completion status.
  861. --***************************************************************************/
  862. NTSTATUS
  863. UlAddUrlToConfigGroupIoctl(
  864. IN PIRP pIrp,
  865. IN PIO_STACK_LOCATION pIrpSp
  866. )
  867. {
  868. NTSTATUS Status;
  869. PHTTP_CONFIG_GROUP_URL_INFO pInfo = NULL;
  870. //
  871. // sanity check.
  872. //
  873. PAGED_CODE();
  874. // better be a control channel
  875. //
  876. if (IS_CONTROL_CHANNEL(pIrpSp->FileObject) == FALSE)
  877. {
  878. // Not a control channel.
  879. //
  880. Status = STATUS_INVALID_DEVICE_REQUEST;
  881. goto end;
  882. }
  883. // Ensure the input buffer is large enough.
  884. //
  885. if (pIrpSp->Parameters.DeviceIoControl.InputBufferLength <
  886. sizeof(HTTP_CONFIG_GROUP_URL_INFO))
  887. {
  888. // bad buffer
  889. //
  890. Status = STATUS_BUFFER_TOO_SMALL;
  891. goto end;
  892. }
  893. // Fetch out the input buffer
  894. //
  895. pInfo = (PHTTP_CONFIG_GROUP_URL_INFO)pIrp->AssociatedIrp.SystemBuffer;
  896. ASSERT(pInfo != NULL);
  897. // does it look appropriate?
  898. //
  899. if (pInfo->FullyQualifiedUrl.MaximumLength < pInfo->FullyQualifiedUrl.Length ||
  900. pInfo->FullyQualifiedUrl.Length == 0 ||
  901. (pInfo->FullyQualifiedUrl.Length % sizeof(WCHAR)) != 0 ||
  902. pInfo->FullyQualifiedUrl.Buffer == NULL)
  903. {
  904. Status = STATUS_INVALID_PARAMETER;
  905. goto end;
  906. }
  907. // Going to access the url string from user mode memory
  908. //
  909. __try
  910. {
  911. // good memory?
  912. //
  913. ProbeTestForRead(pInfo->FullyQualifiedUrl.Buffer,
  914. pInfo->FullyQualifiedUrl.Length + sizeof(WCHAR),
  915. sizeof(WCHAR));
  916. // must be null terminated
  917. //
  918. if (pInfo->FullyQualifiedUrl.Buffer[pInfo->FullyQualifiedUrl.Length/sizeof(WCHAR)] != UNICODE_NULL)
  919. {
  920. Status = STATUS_INVALID_PARAMETER;
  921. __leave;
  922. }
  923. // CODEWORK: validate the incoming url.
  924. //
  925. // Call the internal worker func
  926. //
  927. Status = UlAddUrlToConfigGroup(pInfo->ConfigGroupId, &pInfo->FullyQualifiedUrl, pInfo->UrlContext);
  928. if (NT_SUCCESS(Status) == FALSE)
  929. __leave;
  930. }
  931. __except( UL_EXCEPTION_FILTER() )
  932. {
  933. Status = UL_CONVERT_EXCEPTION_CODE(GetExceptionCode());
  934. }
  935. if (NT_SUCCESS(Status) == FALSE)
  936. goto end;
  937. end:
  938. // complete the request.
  939. //
  940. if (Status != STATUS_PENDING)
  941. {
  942. pIrp->IoStatus.Status = Status;
  943. UlCompleteRequest( pIrp, g_UlPriorityBoost );
  944. }
  945. RETURN( Status );
  946. } // UlAddUrlToConfigGroupIoctl
  947. /***************************************************************************++
  948. Routine Description:
  949. This routine removes a URL prefix from a configuration group.
  950. Note: This is a METHOD_BUFFERED IOCTL.
  951. Arguments:
  952. pIrp - Supplies a pointer to the IO request packet.
  953. pIrpSp - Supplies a pointer to the IO stack location to use for this
  954. request.
  955. Return Value:
  956. NTSTATUS - Completion status.
  957. --***************************************************************************/
  958. NTSTATUS
  959. UlRemoveUrlFromConfigGroupIoctl(
  960. IN PIRP pIrp,
  961. IN PIO_STACK_LOCATION pIrpSp
  962. )
  963. {
  964. NTSTATUS Status;
  965. PHTTP_CONFIG_GROUP_URL_INFO pInfo = NULL;
  966. //
  967. // sanity check.
  968. //
  969. PAGED_CODE();
  970. // better be a control channel
  971. //
  972. if (IS_CONTROL_CHANNEL(pIrpSp->FileObject) == FALSE)
  973. {
  974. // Not a control channel.
  975. //
  976. Status = STATUS_INVALID_DEVICE_REQUEST;
  977. goto end;
  978. }
  979. // Ensure the input buffer is large enough.
  980. //
  981. if (pIrpSp->Parameters.DeviceIoControl.InputBufferLength <
  982. sizeof(HTTP_CONFIG_GROUP_URL_INFO))
  983. {
  984. // bad buffer
  985. //
  986. Status = STATUS_BUFFER_TOO_SMALL;
  987. goto end;
  988. }
  989. // Fetch out the input buffer
  990. //
  991. pInfo = (PHTTP_CONFIG_GROUP_URL_INFO)pIrp->AssociatedIrp.SystemBuffer;
  992. ASSERT(pInfo != NULL);
  993. // does it look appropriate?
  994. //
  995. if (pInfo->FullyQualifiedUrl.MaximumLength < pInfo->FullyQualifiedUrl.Length ||
  996. pInfo->FullyQualifiedUrl.Length == 0 ||
  997. (pInfo->FullyQualifiedUrl.Length % sizeof(WCHAR)) != 0 ||
  998. pInfo->FullyQualifiedUrl.Buffer == NULL)
  999. {
  1000. Status = STATUS_INVALID_PARAMETER;
  1001. goto end;
  1002. }
  1003. // Going to access the url string from user mode memory
  1004. //
  1005. __try
  1006. {
  1007. // good memory?
  1008. //
  1009. ProbeTestForRead(pInfo->FullyQualifiedUrl.Buffer,
  1010. pInfo->FullyQualifiedUrl.Length + sizeof(WCHAR),
  1011. sizeof(WCHAR));
  1012. // must be null terminated
  1013. //
  1014. if (pInfo->FullyQualifiedUrl.Buffer[pInfo->FullyQualifiedUrl.Length/sizeof(WCHAR)] != UNICODE_NULL)
  1015. {
  1016. Status = STATUS_INVALID_PARAMETER;
  1017. __leave;
  1018. }
  1019. // CODEWORK: validate the incoming url.
  1020. //
  1021. // Call the internal worker func
  1022. //
  1023. Status = UlRemoveUrlFromConfigGroup(pInfo->ConfigGroupId, &pInfo->FullyQualifiedUrl);
  1024. if (NT_SUCCESS(Status) == FALSE)
  1025. __leave;
  1026. }
  1027. __except( UL_EXCEPTION_FILTER() )
  1028. {
  1029. Status = UL_CONVERT_EXCEPTION_CODE(GetExceptionCode());
  1030. }
  1031. if (NT_SUCCESS(Status) == FALSE)
  1032. goto end;
  1033. end:
  1034. // complete the request.
  1035. //
  1036. if (Status != STATUS_PENDING)
  1037. {
  1038. pIrp->IoStatus.Status = Status;
  1039. UlCompleteRequest( pIrp, g_UlPriorityBoost );
  1040. }
  1041. RETURN( Status );
  1042. } // UlRemoveUrlFromConfigGroupIoctl
  1043. /***************************************************************************++
  1044. Routine Description:
  1045. This routine removes all URLs from a configuration group.
  1046. Note: This is a METHOD_BUFFERED IOCTL.
  1047. Arguments:
  1048. pIrp - Supplies a pointer to the IO request packet.
  1049. pIrpSp - Supplies a pointer to the IO stack location to use for this
  1050. request.
  1051. Return Value:
  1052. NTSTATUS - Completion status.
  1053. --***************************************************************************/
  1054. NTSTATUS
  1055. UlRemoveAllUrlsFromConfigGroupIoctl(
  1056. IN PIRP pIrp,
  1057. IN PIO_STACK_LOCATION pIrpSp
  1058. )
  1059. {
  1060. NTSTATUS status;
  1061. PHTTP_REMOVE_ALL_URLS_INFO pInfo = NULL;
  1062. //
  1063. // Sanity check.
  1064. //
  1065. PAGED_CODE();
  1066. //
  1067. // Ensure it's a control channel.
  1068. //
  1069. if (IS_CONTROL_CHANNEL(pIrpSp->FileObject) == FALSE)
  1070. {
  1071. status = STATUS_INVALID_DEVICE_REQUEST;
  1072. goto end;
  1073. }
  1074. //
  1075. // Ensure the input buffer is large enough.
  1076. //
  1077. if (pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(*pInfo))
  1078. {
  1079. status = STATUS_BUFFER_TOO_SMALL;
  1080. goto end;
  1081. }
  1082. //
  1083. // Fetch out the input buffer.
  1084. //
  1085. pInfo = (PHTTP_REMOVE_ALL_URLS_INFO)pIrp->AssociatedIrp.SystemBuffer;
  1086. ASSERT(pInfo != NULL);
  1087. //
  1088. // Call the internal worker function.
  1089. //
  1090. status = UlRemoveAllUrlsFromConfigGroup( pInfo->ConfigGroupId );
  1091. goto end;
  1092. end:
  1093. //
  1094. // Complete the request.
  1095. //
  1096. if (status != STATUS_PENDING)
  1097. {
  1098. pIrp->IoStatus.Status = status;
  1099. UlCompleteRequest( pIrp, g_UlPriorityBoost );
  1100. }
  1101. RETURN( status );
  1102. } // UlRemoveAllUrlsFromConfigGroupIoctl
  1103. /***************************************************************************++
  1104. Routine Description:
  1105. This routine queries information associated with an application pool.
  1106. Note: This is a METHOD_OUT_DIRECT IOCTL.
  1107. Arguments:
  1108. pIrp - Supplies a pointer to the IO request packet.
  1109. pIrpSp - Supplies a pointer to the IO stack location to use for this
  1110. request.
  1111. Return Value:
  1112. NTSTATUS - Completion status.
  1113. --***************************************************************************/
  1114. NTSTATUS
  1115. UlQueryAppPoolInformationIoctl(
  1116. IN PIRP pIrp,
  1117. IN PIO_STACK_LOCATION pIrpSp
  1118. )
  1119. {
  1120. NTSTATUS Status;
  1121. PHTTP_APP_POOL_INFO pInfo = NULL;
  1122. PVOID pMdlBuffer;
  1123. ULONG length;
  1124. PVOID pMdlVa;
  1125. //
  1126. // sanity check.
  1127. //
  1128. PAGED_CODE();
  1129. //
  1130. // better be an application pool
  1131. //
  1132. if (!IS_APP_POOL(pIrpSp->FileObject))
  1133. {
  1134. //
  1135. // Not an application pool.
  1136. //
  1137. Status = STATUS_INVALID_DEVICE_REQUEST;
  1138. goto end;
  1139. }
  1140. //
  1141. // Ensure the input buffer looks good
  1142. //
  1143. if (pIrpSp->Parameters.DeviceIoControl.InputBufferLength <
  1144. sizeof(HTTP_APP_POOL_INFO))
  1145. {
  1146. //
  1147. // input buffer too small.
  1148. //
  1149. Status = STATUS_BUFFER_TOO_SMALL;
  1150. goto end;
  1151. }
  1152. pInfo = (PHTTP_APP_POOL_INFO) pIrp->AssociatedIrp.SystemBuffer;
  1153. ASSERT(pInfo != NULL);
  1154. __try
  1155. {
  1156. switch (pInfo->InformationClass)
  1157. {
  1158. case HttpAppPoolDemandStartInformation:
  1159. case HttpAppPoolDemandStartFlagInformation:
  1160. case HttpAppPoolQueueLengthInformation:
  1161. case HttpAppPoolStateInformation:
  1162. // if no outbut buffer passed down in the Irp
  1163. // that means app is asking for the required
  1164. // field length
  1165. if (!pIrp->MdlAddress)
  1166. {
  1167. pMdlBuffer = NULL;
  1168. }
  1169. else
  1170. {
  1171. pMdlBuffer = MmGetSystemAddressForMdlSafe(
  1172. pIrp->MdlAddress,
  1173. LowPagePriority
  1174. );
  1175. if (pMdlBuffer == NULL)
  1176. {
  1177. Status = STATUS_INSUFFICIENT_RESOURCES;
  1178. __leave;
  1179. }
  1180. // Probe the user memory to make sure that it's good.
  1181. pMdlVa = MmGetMdlVirtualAddress(pIrp->MdlAddress);
  1182. ProbeForWrite( pMdlVa,
  1183. pIrpSp->Parameters.DeviceIoControl.OutputBufferLength,
  1184. sizeof(UCHAR) );
  1185. }
  1186. Status = UlQueryAppPoolInformation(
  1187. GET_APP_POOL_PROCESS(pIrpSp->FileObject),
  1188. pInfo->InformationClass,
  1189. pMdlBuffer,
  1190. pIrpSp->Parameters.DeviceIoControl.OutputBufferLength,
  1191. &length
  1192. );
  1193. if (!NT_SUCCESS(Status))
  1194. {
  1195. __leave;
  1196. }
  1197. pIrp->IoStatus.Information = (ULONG_PTR)length;
  1198. break;
  1199. default:
  1200. Status = STATUS_INVALID_PARAMETER;
  1201. __leave;
  1202. break;
  1203. }
  1204. }
  1205. __except( UL_EXCEPTION_FILTER() )
  1206. {
  1207. Status = UL_CONVERT_EXCEPTION_CODE(GetExceptionCode());
  1208. }
  1209. end:
  1210. //
  1211. // complete the request.
  1212. //
  1213. if (Status != STATUS_PENDING)
  1214. {
  1215. pIrp->IoStatus.Status = Status;
  1216. UlCompleteRequest( pIrp, g_UlPriorityBoost );
  1217. }
  1218. RETURN( Status );
  1219. } // UlQueryAppPoolInformationIoctl
  1220. /***************************************************************************++
  1221. Routine Description:
  1222. This routine sets information associated with an application pool.
  1223. Note: This is a METHOD_IN_DIRECT IOCTL.
  1224. Arguments:
  1225. pIrp - Supplies a pointer to the IO request packet.
  1226. pIrpSp - Supplies a pointer to the IO stack location to use for this
  1227. request.
  1228. Return Value:
  1229. NTSTATUS - Completion status.
  1230. --***************************************************************************/
  1231. NTSTATUS
  1232. UlSetAppPoolInformationIoctl(
  1233. IN PIRP pIrp,
  1234. IN PIO_STACK_LOCATION pIrpSp
  1235. )
  1236. {
  1237. NTSTATUS Status;
  1238. PHTTP_APP_POOL_INFO pInfo;
  1239. PVOID pMdlBuffer;
  1240. //
  1241. // Sanity check
  1242. //
  1243. PAGED_CODE();
  1244. //
  1245. // better be an application pool
  1246. //
  1247. if (!IS_APP_POOL(pIrpSp->FileObject))
  1248. {
  1249. //
  1250. // Not an application pool.
  1251. //
  1252. Status = STATUS_INVALID_DEVICE_REQUEST;
  1253. goto end;
  1254. }
  1255. //
  1256. // Ensure the input buffer looks good
  1257. //
  1258. if (pIrpSp->Parameters.DeviceIoControl.InputBufferLength <
  1259. sizeof(HTTP_APP_POOL_INFO))
  1260. {
  1261. //
  1262. // input buffer too small.
  1263. //
  1264. Status = STATUS_BUFFER_TOO_SMALL;
  1265. goto end;
  1266. }
  1267. //
  1268. // Check that the input buffer is valid
  1269. //
  1270. if (NULL == pIrp->MdlAddress)
  1271. {
  1272. Status = STATUS_INVALID_PARAMETER;
  1273. goto end;
  1274. }
  1275. __try
  1276. {
  1277. pInfo = (PHTTP_APP_POOL_INFO) pIrp->AssociatedIrp.SystemBuffer;
  1278. switch (pInfo->InformationClass)
  1279. {
  1280. case HttpAppPoolDemandStartInformation:
  1281. case HttpAppPoolDemandStartFlagInformation:
  1282. case HttpAppPoolQueueLengthInformation:
  1283. case HttpAppPoolStateInformation:
  1284. //
  1285. // call the function
  1286. //
  1287. pMdlBuffer = MmGetSystemAddressForMdlSafe(
  1288. pIrp->MdlAddress,
  1289. LowPagePriority
  1290. );
  1291. if (pMdlBuffer == NULL)
  1292. {
  1293. Status = STATUS_INSUFFICIENT_RESOURCES;
  1294. }
  1295. else
  1296. {
  1297. Status = UlSetAppPoolInformation(
  1298. GET_APP_POOL_PROCESS(pIrpSp->FileObject),
  1299. pInfo->InformationClass,
  1300. pMdlBuffer,
  1301. pIrpSp->Parameters.DeviceIoControl.OutputBufferLength
  1302. );
  1303. }
  1304. break;
  1305. default:
  1306. Status = STATUS_INVALID_PARAMETER;
  1307. break;
  1308. }
  1309. }
  1310. __except( UL_EXCEPTION_FILTER() )
  1311. {
  1312. Status = UL_CONVERT_EXCEPTION_CODE(GetExceptionCode());
  1313. goto end;
  1314. }
  1315. end:
  1316. //
  1317. // complete the request.
  1318. //
  1319. if (Status != STATUS_PENDING)
  1320. {
  1321. pIrp->IoStatus.Status = Status;
  1322. UlCompleteRequest( pIrp, g_UlPriorityBoost );
  1323. }
  1324. RETURN( Status );
  1325. } // UlSetAppPoolInformationIoctl
  1326. /***************************************************************************++
  1327. Routine Description:
  1328. This routine receives an HTTP request.
  1329. Note: This is a METHOD_OUT_DIRECT IOCTL.
  1330. Arguments:
  1331. pIrp - Supplies a pointer to the IO request packet.
  1332. pIrpSp - Supplies a pointer to the IO stack location to use for this
  1333. request.
  1334. Return Value:
  1335. NTSTATUS - Completion status.
  1336. --***************************************************************************/
  1337. NTSTATUS
  1338. UlReceiveHttpRequestIoctl(
  1339. IN PIRP pIrp,
  1340. IN PIO_STACK_LOCATION pIrpSp
  1341. )
  1342. {
  1343. NTSTATUS Status;
  1344. PHTTP_RECEIVE_REQUEST_INFO pInfo = NULL;
  1345. //
  1346. // Sanity check.
  1347. //
  1348. PAGED_CODE();
  1349. //
  1350. // Ensure this is really an app pool, not a control channel.
  1351. //
  1352. if (IS_APP_POOL(pIrpSp->FileObject))
  1353. {
  1354. //
  1355. // Grab the input buffer
  1356. //
  1357. pInfo = (PHTTP_RECEIVE_REQUEST_INFO) pIrp->AssociatedIrp.SystemBuffer;
  1358. if (NULL == pInfo)
  1359. {
  1360. Status = STATUS_INVALID_PARAMETER;
  1361. goto end;
  1362. }
  1363. //
  1364. // first make sure the output buffer is at least
  1365. // minimum size. this is important as we require
  1366. // at least this much space later
  1367. //
  1368. UlTrace(ROUTING, (
  1369. "UlReceiveHttpRequestIoctl(outbuf=%d, inbuf=%d)\n",
  1370. pIrpSp->Parameters.DeviceIoControl.OutputBufferLength,
  1371. pIrpSp->Parameters.DeviceIoControl.InputBufferLength
  1372. ));
  1373. if ((pIrpSp->Parameters.DeviceIoControl.OutputBufferLength >=
  1374. sizeof(HTTP_REQUEST)) &&
  1375. (pIrpSp->Parameters.DeviceIoControl.InputBufferLength ==
  1376. sizeof(HTTP_RECEIVE_REQUEST_INFO)))
  1377. {
  1378. Status = UlReceiveHttpRequest(
  1379. pInfo->RequestId,
  1380. pInfo->Flags,
  1381. GET_APP_POOL_PROCESS(pIrpSp->FileObject),
  1382. pIrp
  1383. );
  1384. }
  1385. else
  1386. {
  1387. Status = STATUS_BUFFER_TOO_SMALL;
  1388. // Add some padding
  1389. pIrp->IoStatus.Information = 3 * sizeof(HTTP_REQUEST) / 2;
  1390. }
  1391. UlTrace(ROUTING, (
  1392. "UlReceiveHttpRequestIoctl: BytesNeeded=%d, status=0x%x\n",
  1393. pIrp->IoStatus.Information, Status
  1394. ));
  1395. }
  1396. else
  1397. {
  1398. Status = STATUS_INVALID_DEVICE_REQUEST;
  1399. }
  1400. end:
  1401. //
  1402. // Complete the request.
  1403. //
  1404. if (Status != STATUS_PENDING)
  1405. {
  1406. pIrp->IoStatus.Status = Status;
  1407. UlCompleteRequest( pIrp, g_UlPriorityBoost );
  1408. }
  1409. RETURN( Status );
  1410. } // UlReceiveHttpRequestIoctl
  1411. /***************************************************************************++
  1412. Routine Description:
  1413. This routine receives entity body data from an HTTP request.
  1414. Note: This is a METHOD_BUFFERED IOCTL.
  1415. Arguments:
  1416. pIrp - Supplies a pointer to the IO request packet.
  1417. pIrpSp - Supplies a pointer to the IO stack location to use for this
  1418. request.
  1419. Return Value:
  1420. NTSTATUS - Completion status.
  1421. --***************************************************************************/
  1422. NTSTATUS
  1423. UlReceiveEntityBodyIoctl(
  1424. IN PIRP pIrp,
  1425. IN PIO_STACK_LOCATION pIrpSp
  1426. )
  1427. {
  1428. NTSTATUS Status;
  1429. PHTTP_RECEIVE_REQUEST_INFO pInfo;
  1430. PUL_INTERNAL_REQUEST pRequest = NULL;
  1431. //
  1432. // Sanity check.
  1433. //
  1434. PAGED_CODE();
  1435. //
  1436. // Ensure this is really an app pool, not a control channel.
  1437. //
  1438. if (IS_APP_POOL(pIrpSp->FileObject) == FALSE)
  1439. {
  1440. Status = STATUS_INVALID_DEVICE_REQUEST;
  1441. goto end;
  1442. }
  1443. //
  1444. // Ensure the input buffer is large enough.
  1445. //
  1446. if (pIrpSp->Parameters.DeviceIoControl.InputBufferLength <
  1447. sizeof(HTTP_RECEIVE_REQUEST_INFO))
  1448. {
  1449. Status = STATUS_BUFFER_TOO_SMALL;
  1450. goto end;
  1451. }
  1452. //
  1453. // Map the incoming connection ID to the corresponding
  1454. // PUL_HTTP_CONNECTION object.
  1455. //
  1456. pInfo = (PHTTP_RECEIVE_REQUEST_INFO)(pIrp->AssociatedIrp.SystemBuffer);
  1457. //
  1458. // Now get the request from the request id.
  1459. // This gets us a reference to the request.
  1460. //
  1461. pRequest = UlGetRequestFromId(pInfo->RequestId);
  1462. if (UL_IS_VALID_INTERNAL_REQUEST(pRequest) == FALSE)
  1463. {
  1464. Status = STATUS_INVALID_PARAMETER;
  1465. goto end;
  1466. }
  1467. //
  1468. // OK, now call the function
  1469. //
  1470. Status = UlReceiveEntityBody(
  1471. GET_APP_POOL_PROCESS(pIrpSp->FileObject),
  1472. pRequest,
  1473. pIrp
  1474. );
  1475. if (NT_SUCCESS(Status) == FALSE)
  1476. goto end;
  1477. end:
  1478. if (pRequest != NULL)
  1479. {
  1480. UL_DEREFERENCE_INTERNAL_REQUEST(pRequest);
  1481. pRequest = NULL;
  1482. }
  1483. //
  1484. // Complete the request.
  1485. //
  1486. if (Status != STATUS_PENDING)
  1487. {
  1488. pIrp->IoStatus.Status = Status;
  1489. UlCompleteRequest( pIrp, g_UlPriorityBoost );
  1490. }
  1491. RETURN( Status );
  1492. } // UlReceiveEntityBodyIoctl
  1493. /***************************************************************************++
  1494. Routine Description:
  1495. This routine sends an HTTP response.
  1496. Note: This is a METHOD_BUFFERED IOCTL.
  1497. Arguments:
  1498. pIrp - Supplies a pointer to the IO request packet.
  1499. pIrpSp - Supplies a pointer to the IO stack location to use for this
  1500. request.
  1501. Return Value:
  1502. NTSTATUS - Completion status.
  1503. --***************************************************************************/
  1504. NTSTATUS
  1505. UlSendHttpResponseIoctl(
  1506. IN PIRP pIrp,
  1507. IN PIO_STACK_LOCATION pIrpSp
  1508. )
  1509. {
  1510. NTSTATUS Status = STATUS_SUCCESS;
  1511. PHTTP_SEND_HTTP_RESPONSE_INFO pSendInfo = NULL;
  1512. PUL_INTERNAL_RESPONSE pResponse = NULL;
  1513. PHTTP_RESPONSE pHttpResponse = NULL;
  1514. ULONG Flags;
  1515. PUL_INTERNAL_REQUEST pRequest = NULL;
  1516. BOOLEAN ServedFromCache = FALSE;
  1517. BOOLEAN CaptureCache;
  1518. BOOLEAN ConnectionClosed = FALSE;
  1519. //
  1520. // Sanity check.
  1521. //
  1522. PAGED_CODE();
  1523. //
  1524. // Ensure this is really an app pool, not a control channel.
  1525. //
  1526. if (IS_APP_POOL(pIrpSp->FileObject) == FALSE)
  1527. {
  1528. //
  1529. // Not an app pool.
  1530. //
  1531. Status = STATUS_INVALID_DEVICE_REQUEST;
  1532. goto end;
  1533. }
  1534. //
  1535. // Ensure the input buffer is large enough.
  1536. //
  1537. if (pIrpSp->Parameters.DeviceIoControl.InputBufferLength <
  1538. sizeof(*pSendInfo))
  1539. {
  1540. //
  1541. // Input buffer too small.
  1542. //
  1543. Status = STATUS_BUFFER_TOO_SMALL;
  1544. goto end;
  1545. }
  1546. pSendInfo = (PHTTP_SEND_HTTP_RESPONSE_INFO)pIrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
  1547. //
  1548. // Probe pSendInfo since we use NEITHER_IO.
  1549. //
  1550. __try
  1551. {
  1552. ProbeTestForRead(
  1553. pSendInfo,
  1554. sizeof(*pSendInfo),
  1555. sizeof(PVOID)
  1556. );
  1557. ProbeTestForRead(
  1558. pSendInfo->pEntityChunks,
  1559. sizeof(HTTP_DATA_CHUNK) * pSendInfo->EntityChunkCount,
  1560. sizeof(PVOID)
  1561. );
  1562. UlTrace(SEND_RESPONSE, (
  1563. "UL!UlSendHttpResponseIoctl - Flags = %X\n",
  1564. pSendInfo->Flags
  1565. ));
  1566. //
  1567. // UlSendHttpResponse() *must* take a PHTTP_RESPONSE. This will
  1568. // protect us from those whackos that attempt to build their own
  1569. // raw response headers.
  1570. //
  1571. pHttpResponse = pSendInfo->pHttpResponse;
  1572. if (pHttpResponse == NULL)
  1573. {
  1574. Status = STATUS_INVALID_PARAMETER;
  1575. goto end;
  1576. }
  1577. //
  1578. // Now get the request from the request id.
  1579. // This gives us a reference to the request.
  1580. //
  1581. pRequest = UlGetRequestFromId(pSendInfo->RequestId);
  1582. if (pRequest == NULL)
  1583. {
  1584. //
  1585. // Couldn't map the HTTP_REQUEST_ID.
  1586. //
  1587. Status = STATUS_INVALID_PARAMETER;
  1588. goto end;
  1589. }
  1590. ASSERT(UL_IS_VALID_INTERNAL_REQUEST(pRequest));
  1591. ASSERT(UL_IS_VALID_HTTP_CONNECTION(pRequest->pHttpConn));
  1592. //
  1593. // Make sure only one response header goes back. We can test this
  1594. // without acquiring the request resource, since the flag is only set
  1595. // (never reset).
  1596. //
  1597. if (1 == InterlockedCompareExchange(
  1598. (PLONG)&pRequest->SentResponse,
  1599. 1,
  1600. 0
  1601. ))
  1602. {
  1603. //
  1604. // already sent a response. bad.
  1605. //
  1606. Status = STATUS_INVALID_DEVICE_STATE;
  1607. UlTrace(SEND_RESPONSE, (
  1608. "ul!UlSendHttpResponseIoctl(pRequest = %p (%I64x)) %x\n"
  1609. " Tried to send a second response!\n",
  1610. pRequest,
  1611. pRequest->RequestId,
  1612. Status
  1613. ));
  1614. goto end;
  1615. }
  1616. //
  1617. // Also ensure that all previous calls to SendHttpResponse
  1618. // and SendEntityBody had the MORE_DATA flag set.
  1619. //
  1620. if ((pSendInfo->Flags & HTTP_SEND_RESPONSE_FLAG_MORE_DATA) == 0)
  1621. {
  1622. //
  1623. // Remember if the more data flag is not set.
  1624. //
  1625. if (1 == InterlockedCompareExchange(
  1626. (PLONG)&pRequest->SentLast,
  1627. 1,
  1628. 0
  1629. ))
  1630. {
  1631. Status = STATUS_INVALID_DEVICE_STATE;
  1632. goto end;
  1633. }
  1634. }
  1635. else
  1636. if (pRequest->SentLast == 1)
  1637. {
  1638. Status = STATUS_INVALID_DEVICE_STATE;
  1639. UlTrace(SEND_RESPONSE, (
  1640. "ul!UlSendHttpResponseIoctl(pRequest = %p (%I64x)) %x\n"
  1641. " Tried to send again after last send!\n",
  1642. pRequest,
  1643. pRequest->RequestId,
  1644. Status
  1645. ));
  1646. goto end;
  1647. }
  1648. //
  1649. // OK, we have the connection. Now capture the incoming
  1650. // HTTP_RESPONSE structure and map it to our internal
  1651. // format.
  1652. //
  1653. if (pSendInfo->CachePolicy.Policy != HttpCachePolicyNocache)
  1654. {
  1655. CaptureCache = pRequest->CachePreconditions;
  1656. }
  1657. else
  1658. {
  1659. CaptureCache = FALSE;
  1660. }
  1661. //
  1662. // Take the fast path if this is a single memory chunk that needs no
  1663. // retransmission (<= 64k).
  1664. //
  1665. if (CaptureCache == FALSE
  1666. && pSendInfo->EntityChunkCount == 1
  1667. && pSendInfo->pEntityChunks->DataChunkType
  1668. == HttpDataChunkFromMemory
  1669. && pSendInfo->pEntityChunks->FromMemory.BufferLength
  1670. <= MAX_BYTES_BUFFERED
  1671. )
  1672. {
  1673. Status = UlpFastSendHttpResponse(
  1674. pSendInfo->pHttpResponse,
  1675. pSendInfo->pLogData,
  1676. pSendInfo->pEntityChunks,
  1677. 1,
  1678. pSendInfo->Flags,
  1679. pRequest,
  1680. pIrp,
  1681. NULL
  1682. );
  1683. goto end;
  1684. }
  1685. Status = UlCaptureHttpResponse(
  1686. pSendInfo->pHttpResponse,
  1687. pRequest,
  1688. pRequest->Version,
  1689. pRequest->Verb,
  1690. pSendInfo->EntityChunkCount,
  1691. pSendInfo->pEntityChunks,
  1692. UlCaptureNothing,
  1693. CaptureCache,
  1694. pSendInfo->pLogData,
  1695. &pResponse
  1696. );
  1697. }
  1698. __except( UL_EXCEPTION_FILTER() )
  1699. {
  1700. Status = UL_CONVERT_EXCEPTION_CODE(GetExceptionCode());
  1701. }
  1702. if (NT_SUCCESS(Status) == FALSE)
  1703. goto end;
  1704. //
  1705. // Save the captured response in the IRP so we can
  1706. // dereference it after the IRP completes.
  1707. //
  1708. pIrpSp->Parameters.DeviceIoControl.Type3InputBuffer = pResponse;
  1709. //
  1710. // Prepare the response (open files, etc).
  1711. //
  1712. Status = UlPrepareHttpResponse(
  1713. pRequest->Version,
  1714. pHttpResponse,
  1715. pResponse
  1716. );
  1717. if (NT_SUCCESS(Status))
  1718. {
  1719. //
  1720. // At this point, we'll definitely be initiating the
  1721. // send. Go ahead and mark the IRP as pending, then
  1722. // guarantee that we'll only return pending from
  1723. // this point on.
  1724. //
  1725. IoMarkIrpPending( pIrp );
  1726. pIrp->IoStatus.Status = STATUS_PENDING;
  1727. //
  1728. // Try capture to cache and send
  1729. //
  1730. if (CaptureCache)
  1731. {
  1732. Status = UlCacheAndSendResponse(
  1733. pRequest,
  1734. pResponse,
  1735. GET_APP_POOL_PROCESS( pIrpSp->FileObject ),
  1736. pSendInfo->Flags,
  1737. pSendInfo->CachePolicy,
  1738. &UlpRestartSendHttpResponse,
  1739. pIrp,
  1740. &ServedFromCache
  1741. );
  1742. if (NT_SUCCESS(Status) && !ServedFromCache)
  1743. {
  1744. //
  1745. // Send the non-cached response
  1746. //
  1747. Status = UlSendHttpResponse(
  1748. pRequest,
  1749. pResponse,
  1750. pSendInfo->Flags,
  1751. &UlpRestartSendHttpResponse,
  1752. pIrp
  1753. );
  1754. }
  1755. }
  1756. else
  1757. {
  1758. //
  1759. // Non-cacheable request/response, send response directly.
  1760. //
  1761. Status = UlSendHttpResponse(
  1762. pRequest,
  1763. pResponse,
  1764. pSendInfo->Flags,
  1765. &UlpRestartSendHttpResponse,
  1766. pIrp
  1767. );
  1768. }
  1769. }
  1770. else
  1771. {
  1772. //
  1773. // BUGBUG: Do custom error thang here.
  1774. //
  1775. NTSTATUS CloseStatus;
  1776. pIrp->IoStatus.Status = Status;
  1777. CloseStatus = UlCloseConnection(
  1778. pRequest->pHttpConn->pConnection,
  1779. TRUE,
  1780. &UlpRestartSendHttpResponse,
  1781. pIrp
  1782. );
  1783. ASSERT( CloseStatus == STATUS_PENDING );
  1784. ConnectionClosed = TRUE;
  1785. // UlCloseConnection always returns STATUS_PENDING
  1786. // but we want to return the a proper error code here.
  1787. // E.G. If the supplied file - as filename data chunk -
  1788. // not found we will return STATUS_OBJECT_NAME_INVALID
  1789. // as its returned by UlPrepareHttpResponse.
  1790. }
  1791. // paulmcd: is this the right time to deref?
  1792. //
  1793. // DEREFERENCE_HTTP_CONNECTION( pHttpConnection );
  1794. if (Status != STATUS_PENDING && !ConnectionClosed)
  1795. {
  1796. //
  1797. // UlSendHttpResponse either completed in-line
  1798. // (extremely unlikely) or failed (much more
  1799. // likely). Fake a completion to the completion
  1800. // routine so that the IRP will get completed
  1801. // properly, then map the return code to
  1802. // STATUS_PENDING, since we've already marked
  1803. // the IRP as such.
  1804. //
  1805. UlpRestartSendHttpResponse(
  1806. pIrp,
  1807. Status,
  1808. 0
  1809. );
  1810. Status = STATUS_PENDING;
  1811. }
  1812. end:
  1813. if (pRequest != NULL)
  1814. {
  1815. UL_DEREFERENCE_INTERNAL_REQUEST(pRequest);
  1816. pRequest = NULL;
  1817. }
  1818. //
  1819. // Complete the request.
  1820. //
  1821. if (Status != STATUS_PENDING && !ConnectionClosed)
  1822. {
  1823. pIrp->IoStatus.Status = Status;
  1824. UlCompleteRequest( pIrp, g_UlPriorityBoost );
  1825. }
  1826. RETURN( Status );
  1827. } // UlSendHttpResponseIoctl
  1828. /***************************************************************************++
  1829. Routine Description:
  1830. This routine sends an HTTP entity body.
  1831. Note: This is a METHOD_BUFFERED IOCTL.
  1832. Arguments:
  1833. pIrp - Supplies a pointer to the IO request packet.
  1834. pIrpSp - Supplies a pointer to the IO stack location to use for this
  1835. request.
  1836. Return Value:
  1837. NTSTATUS - Completion status.
  1838. --***************************************************************************/
  1839. NTSTATUS
  1840. UlSendEntityBodyIoctl(
  1841. IN PIRP pIrp,
  1842. IN PIO_STACK_LOCATION pIrpSp
  1843. )
  1844. {
  1845. NTSTATUS Status;
  1846. PHTTP_SEND_HTTP_RESPONSE_INFO pSendInfo;
  1847. PUL_INTERNAL_RESPONSE pResponse;
  1848. ULONG Flags;
  1849. PUL_INTERNAL_REQUEST pRequest = NULL;
  1850. BOOLEAN ConnectionClosed = FALSE;
  1851. //
  1852. // Sanity check.
  1853. //
  1854. PAGED_CODE();
  1855. //
  1856. // Ensure this is really an app pool, not a control channel.
  1857. //
  1858. if (IS_APP_POOL(pIrpSp->FileObject) == FALSE)
  1859. {
  1860. //
  1861. // Not an app pool.
  1862. //
  1863. Status = STATUS_INVALID_DEVICE_REQUEST;
  1864. goto end;
  1865. }
  1866. //
  1867. // Ensure the input buffer is large enough.
  1868. //
  1869. if (pIrpSp->Parameters.DeviceIoControl.InputBufferLength <
  1870. sizeof(*pSendInfo))
  1871. {
  1872. //
  1873. // Input buffer too small.
  1874. //
  1875. Status = STATUS_BUFFER_TOO_SMALL;
  1876. goto end;
  1877. }
  1878. pSendInfo = (PHTTP_SEND_HTTP_RESPONSE_INFO)pIrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
  1879. //
  1880. // Probe pSendInfo since we use NEITHER_IO.
  1881. //
  1882. __try
  1883. {
  1884. ProbeTestForRead(
  1885. pSendInfo,
  1886. sizeof(*pSendInfo),
  1887. sizeof(PVOID)
  1888. );
  1889. }
  1890. __except( UL_EXCEPTION_FILTER() )
  1891. {
  1892. Status = UL_CONVERT_EXCEPTION_CODE(GetExceptionCode());
  1893. goto end;
  1894. }
  1895. UlTrace(SEND_RESPONSE, (
  1896. "UL!UlSendEntityBodyIoctl - Flags = %X\n",
  1897. pSendInfo->Flags
  1898. ));
  1899. //
  1900. // Now get the request from the request id.
  1901. // This gives us a reference to the request.
  1902. //
  1903. pRequest = UlGetRequestFromId(pSendInfo->RequestId);
  1904. if (pRequest == NULL)
  1905. {
  1906. //
  1907. // Couldn't map the HTTP_REQUEST_ID.
  1908. //
  1909. Status = STATUS_INVALID_PARAMETER;
  1910. goto end;
  1911. }
  1912. ASSERT(UL_IS_VALID_INTERNAL_REQUEST(pRequest));
  1913. ASSERT(UL_IS_VALID_HTTP_CONNECTION(pRequest->pHttpConn));
  1914. //
  1915. // Ensure a response has already been sent. We can test this without
  1916. // acquiring the request resource, since the flag is only set (never
  1917. // reset).
  1918. //
  1919. if (pRequest->SentResponse == 0)
  1920. {
  1921. //
  1922. // The application is sending entity without first having
  1923. // send a response header. This is generally an error, however
  1924. // we allow the application to override this by passing
  1925. // the HTTP_SEND_RESPONSE_FLAG_RAW_HEADER flag.
  1926. //
  1927. if (pSendInfo->Flags & HTTP_SEND_RESPONSE_FLAG_RAW_HEADER)
  1928. {
  1929. UlTrace(SEND_RESPONSE, (
  1930. "ul!UlSendEntityBodyIoctl(pRequest = %p (%I64x))\n"
  1931. " Intentionally sending raw header!\n",
  1932. pRequest,
  1933. pRequest->RequestId
  1934. ));
  1935. if (1 == InterlockedCompareExchange(
  1936. (PLONG)&pRequest->SentResponse,
  1937. 1,
  1938. 0
  1939. ))
  1940. {
  1941. Status = STATUS_INVALID_DEVICE_STATE;
  1942. goto end;
  1943. }
  1944. }
  1945. else
  1946. {
  1947. Status = STATUS_INVALID_DEVICE_STATE;
  1948. UlTrace(SEND_RESPONSE, (
  1949. "ul!UlSendEntityBodyIoctl(pRequest = %p (%I64x)) %x\n"
  1950. " No response yet!\n",
  1951. pRequest,
  1952. pRequest->RequestId,
  1953. Status
  1954. ));
  1955. goto end;
  1956. }
  1957. }
  1958. //
  1959. // Also ensure that all previous calls to SendHttpResponse
  1960. // and SendEntityBody had the MORE_DATA flag set.
  1961. //
  1962. if ((pSendInfo->Flags & HTTP_SEND_RESPONSE_FLAG_MORE_DATA) == 0)
  1963. {
  1964. //
  1965. // Remember that this was the last send. We shouldn't
  1966. // get any more data after this.
  1967. //
  1968. if (1 == InterlockedCompareExchange(
  1969. (PLONG)&pRequest->SentLast,
  1970. 1,
  1971. 0
  1972. ))
  1973. {
  1974. Status = STATUS_INVALID_DEVICE_STATE;
  1975. goto end;
  1976. }
  1977. }
  1978. else
  1979. if (pRequest->SentLast == 1)
  1980. {
  1981. Status = STATUS_INVALID_DEVICE_STATE;
  1982. UlTrace(SEND_RESPONSE, (
  1983. "ul!UlSendEntityBodyIoctl(pRequest = %p (%I64x)) %x\n"
  1984. " Tried to send again after last send!\n",
  1985. pRequest,
  1986. pRequest->RequestId,
  1987. Status
  1988. ));
  1989. goto end;
  1990. }
  1991. ASSERT(pSendInfo->pHttpResponse == NULL);
  1992. __try
  1993. {
  1994. //
  1995. // Take the fast path if this is a single memory chunk that needs no
  1996. // retransmission (<= 64k).
  1997. //
  1998. if (pSendInfo->EntityChunkCount == 1
  1999. && pSendInfo->pEntityChunks->DataChunkType
  2000. == HttpDataChunkFromMemory
  2001. && pSendInfo->pEntityChunks->FromMemory.BufferLength
  2002. <= MAX_BYTES_BUFFERED
  2003. )
  2004. {
  2005. Status = UlpFastSendHttpResponse(
  2006. NULL,
  2007. pSendInfo->pLogData,
  2008. pSendInfo->pEntityChunks,
  2009. 1,
  2010. pSendInfo->Flags,
  2011. pRequest,
  2012. pIrp,
  2013. NULL
  2014. );
  2015. goto end;
  2016. }
  2017. //
  2018. // OK, we have the connection. Now capture the incoming
  2019. // HTTP_RESPONSE structure and map it to our internal
  2020. // format.
  2021. //
  2022. Status = UlCaptureHttpResponse(
  2023. NULL,
  2024. pRequest,
  2025. pRequest->Version,
  2026. pRequest->Verb,
  2027. pSendInfo->EntityChunkCount,
  2028. pSendInfo->pEntityChunks,
  2029. UlCaptureNothing,
  2030. FALSE,
  2031. pSendInfo->pLogData,
  2032. &pResponse
  2033. );
  2034. }
  2035. __except( UL_EXCEPTION_FILTER() )
  2036. {
  2037. Status = UL_CONVERT_EXCEPTION_CODE(GetExceptionCode());
  2038. }
  2039. if (NT_SUCCESS(Status) == FALSE)
  2040. goto end;
  2041. //
  2042. // Save the captured response in the IRP so we can
  2043. // dereference it after the IRP completes.
  2044. //
  2045. pIrpSp->Parameters.DeviceIoControl.Type3InputBuffer = pResponse;
  2046. //
  2047. // Prepare the response (open files, etc).
  2048. //
  2049. Status = UlPrepareHttpResponse(
  2050. pRequest->Version,
  2051. NULL,
  2052. pResponse
  2053. );
  2054. if (NT_SUCCESS(Status))
  2055. {
  2056. //
  2057. // At this point, we'll definitely be initiating the
  2058. // send. Go ahead and mark the IRP as pending, then
  2059. // guarantee that we'll only return pending from
  2060. // this point on.
  2061. //
  2062. IoMarkIrpPending( pIrp );
  2063. pIrp->IoStatus.Status = STATUS_PENDING;
  2064. //
  2065. // Send the response
  2066. //
  2067. Status = UlSendHttpResponse(
  2068. pRequest,
  2069. pResponse,
  2070. pSendInfo->Flags,
  2071. &UlpRestartSendHttpResponse,
  2072. pIrp
  2073. );
  2074. }
  2075. else
  2076. {
  2077. //
  2078. // BUGBUG: Do custom error thang here.
  2079. //
  2080. NTSTATUS CloseStatus;
  2081. pIrp->IoStatus.Status = Status;
  2082. CloseStatus = UlCloseConnection(
  2083. pRequest->pHttpConn->pConnection,
  2084. TRUE,
  2085. &UlpRestartSendHttpResponse,
  2086. pIrp
  2087. );
  2088. ASSERT( CloseStatus == STATUS_PENDING );
  2089. ConnectionClosed = TRUE;
  2090. }
  2091. // paulmcd: is this the right time to deref?
  2092. //
  2093. // DEREFERENCE_HTTP_CONNECTION( pHttpConnection );
  2094. if (Status != STATUS_PENDING && !ConnectionClosed)
  2095. {
  2096. //
  2097. // UlSendHttpResponse either completed in-line
  2098. // (extremely unlikely) or failed (much more
  2099. // likely). Fake a completion to the completion
  2100. // routine so that the IRP will get completed
  2101. // properly, then map the return code to
  2102. // STATUS_PENDING, since we've already marked
  2103. // the IRP as such.
  2104. //
  2105. UlpRestartSendHttpResponse(
  2106. pIrp,
  2107. Status,
  2108. 0
  2109. );
  2110. Status = STATUS_PENDING;
  2111. }
  2112. end:
  2113. if (pRequest != NULL)
  2114. {
  2115. UL_DEREFERENCE_INTERNAL_REQUEST(pRequest);
  2116. pRequest = NULL;
  2117. }
  2118. //
  2119. // Complete the request.
  2120. //
  2121. if (Status != STATUS_PENDING && !ConnectionClosed)
  2122. {
  2123. pIrp->IoStatus.Status = Status;
  2124. UlCompleteRequest( pIrp, g_UlPriorityBoost );
  2125. }
  2126. RETURN( Status );
  2127. } // UlSendEntityBodyIoctl
  2128. /***************************************************************************++
  2129. Routine Description:
  2130. This routine flushes a URL or URL tree from the response cache.
  2131. Note: This is a METHOD_BUFFERED IOCTL.
  2132. Arguments:
  2133. pIrp - Supplies a pointer to the IO request packet.
  2134. pIrpSp - Supplies a pointer to the IO stack location to use for this
  2135. request.
  2136. Return Value:
  2137. NTSTATUS - Completion status.
  2138. --***************************************************************************/
  2139. NTSTATUS
  2140. UlFlushResponseCacheIoctl(
  2141. IN PIRP pIrp,
  2142. IN PIO_STACK_LOCATION pIrpSp
  2143. )
  2144. {
  2145. NTSTATUS Status;
  2146. PHTTP_FLUSH_RESPONSE_CACHE_INFO pInfo = NULL;
  2147. //
  2148. // sanity check.
  2149. //
  2150. PAGED_CODE();
  2151. // better be an app pool
  2152. //
  2153. if (IS_APP_POOL(pIrpSp->FileObject) == FALSE)
  2154. {
  2155. //
  2156. // Not an app pool.
  2157. //
  2158. Status = STATUS_INVALID_DEVICE_REQUEST;
  2159. goto end;
  2160. }
  2161. // Ensure the input buffer is large enough.
  2162. //
  2163. if (pIrpSp->Parameters.DeviceIoControl.InputBufferLength <
  2164. sizeof(HTTP_FLUSH_RESPONSE_CACHE_INFO))
  2165. {
  2166. // bad buffer
  2167. //
  2168. Status = STATUS_BUFFER_TOO_SMALL;
  2169. goto end;
  2170. }
  2171. // Fetch out the input buffer
  2172. //
  2173. pInfo = (PHTTP_FLUSH_RESPONSE_CACHE_INFO)pIrp->AssociatedIrp.SystemBuffer;
  2174. ASSERT(pInfo != NULL);
  2175. // does it look appropriate?
  2176. //
  2177. if (pInfo->FullyQualifiedUrl.MaximumLength < pInfo->FullyQualifiedUrl.Length ||
  2178. pInfo->FullyQualifiedUrl.Length == 0 ||
  2179. (pInfo->FullyQualifiedUrl.Length % sizeof(WCHAR)) != 0 ||
  2180. pInfo->FullyQualifiedUrl.Buffer == NULL)
  2181. {
  2182. Status = STATUS_INVALID_PARAMETER;
  2183. goto end;
  2184. }
  2185. // Going to access the url string from user mode memory
  2186. //
  2187. __try
  2188. {
  2189. // good memory?
  2190. //
  2191. ProbeTestForRead(pInfo->FullyQualifiedUrl.Buffer,
  2192. pInfo->FullyQualifiedUrl.Length + sizeof(WCHAR),
  2193. sizeof(WCHAR));
  2194. // must be null terminated
  2195. //
  2196. if (pInfo->FullyQualifiedUrl.Buffer[pInfo->FullyQualifiedUrl.Length/sizeof(WCHAR)] != UNICODE_NULL)
  2197. {
  2198. Status = STATUS_INVALID_PARAMETER;
  2199. __leave;
  2200. }
  2201. // check the flags
  2202. //
  2203. if (pInfo->Flags != (pInfo->Flags & HTTP_FLUSH_RESPONSE_FLAG_VALID)) {
  2204. Status = STATUS_INVALID_PARAMETER;
  2205. __leave;
  2206. }
  2207. // Call the internal worker func
  2208. //
  2209. UlFlushCacheByUri(
  2210. pInfo->FullyQualifiedUrl.Buffer,
  2211. pInfo->FullyQualifiedUrl.Length,
  2212. pInfo->Flags,
  2213. GET_APP_POOL_PROCESS( pIrpSp->FileObject )
  2214. );
  2215. Status = STATUS_SUCCESS;
  2216. if (NT_SUCCESS(Status) == FALSE)
  2217. __leave;
  2218. }
  2219. __except( UL_EXCEPTION_FILTER() )
  2220. {
  2221. Status = UL_CONVERT_EXCEPTION_CODE(GetExceptionCode());
  2222. }
  2223. if (NT_SUCCESS(Status) == FALSE)
  2224. goto end;
  2225. end:
  2226. // complete the request.
  2227. //
  2228. if (Status != STATUS_PENDING)
  2229. {
  2230. pIrp->IoStatus.Status = Status;
  2231. UlCompleteRequest( pIrp, g_UlPriorityBoost );
  2232. }
  2233. RETURN( Status );
  2234. } // UlFlushResponseCacheIoctl
  2235. /***************************************************************************++
  2236. Routine Description:
  2237. This routine waits for demand start notifications.
  2238. Note: This is a METHOD_BUFFERED IOCTL.
  2239. Arguments:
  2240. pIrp - Supplies a pointer to the IO request packet.
  2241. pIrpSp - Supplies a pointer to the IO stack location to use for this
  2242. request.
  2243. Return Value:
  2244. NTSTATUS - Completion status.
  2245. --***************************************************************************/
  2246. NTSTATUS
  2247. UlWaitForDemandStartIoctl(
  2248. IN PIRP pIrp,
  2249. IN PIO_STACK_LOCATION pIrpSp
  2250. )
  2251. {
  2252. NTSTATUS Status;
  2253. //
  2254. // sanity check.
  2255. //
  2256. PAGED_CODE();
  2257. //
  2258. // This had better be an app pool.
  2259. //
  2260. if (IS_APP_POOL(pIrpSp->FileObject) == FALSE)
  2261. {
  2262. //
  2263. // Not an app pool.
  2264. //
  2265. Status = STATUS_INVALID_DEVICE_REQUEST;
  2266. goto end;
  2267. }
  2268. //
  2269. // make the call
  2270. //
  2271. UlTrace(IOCTL,
  2272. ("UlWaitForDemandStartIoctl: pAppPoolProcess=%p, pIrp=%p\n",
  2273. GET_APP_POOL_PROCESS(pIrpSp->FileObject),
  2274. pIrp
  2275. ));
  2276. Status = UlWaitForDemandStart(
  2277. GET_APP_POOL_PROCESS(pIrpSp->FileObject),
  2278. pIrp
  2279. );
  2280. end:
  2281. //
  2282. // complete the request?
  2283. //
  2284. if (Status != STATUS_PENDING)
  2285. {
  2286. pIrp->IoStatus.Status = Status;
  2287. UlCompleteRequest( pIrp, g_UlPriorityBoost );
  2288. }
  2289. RETURN( Status );
  2290. } // UlWaitForDemandStartIoctl
  2291. /***************************************************************************++
  2292. Routine Description:
  2293. This routine waits for the client to initiate a disconnect.
  2294. Note: This is a METHOD_BUFFERED IOCTL.
  2295. Arguments:
  2296. pIrp - Supplies a pointer to the IO request packet.
  2297. pIrpSp - Supplies a pointer to the IO stack location to use for this
  2298. request.
  2299. Return Value:
  2300. NTSTATUS - Completion status.
  2301. --***************************************************************************/
  2302. NTSTATUS
  2303. UlWaitForDisconnectIoctl(
  2304. IN PIRP pIrp,
  2305. IN PIO_STACK_LOCATION pIrpSp
  2306. )
  2307. {
  2308. NTSTATUS status;
  2309. PHTTP_WAIT_FOR_DISCONNECT_INFO pInfo;
  2310. PUL_HTTP_CONNECTION pHttpConn;
  2311. //
  2312. // Sanity check.
  2313. //
  2314. PAGED_CODE();
  2315. //
  2316. // This had better be an app pool.
  2317. //
  2318. if (IS_APP_POOL(pIrpSp->FileObject) == FALSE)
  2319. {
  2320. //
  2321. // Not an app pool.
  2322. //
  2323. status = STATUS_INVALID_DEVICE_REQUEST;
  2324. goto end;
  2325. }
  2326. //
  2327. // Validate the input buffer.
  2328. //
  2329. if (pIrpSp->Parameters.DeviceIoControl.InputBufferLength <
  2330. sizeof(*pInfo))
  2331. {
  2332. status = STATUS_BUFFER_TOO_SMALL;
  2333. goto end;
  2334. }
  2335. pInfo = (PHTTP_WAIT_FOR_DISCONNECT_INFO)pIrp->AssociatedIrp.SystemBuffer;
  2336. //
  2337. // Chase down the connection.
  2338. //
  2339. pHttpConn = UlGetConnectionFromId( pInfo->ConnectionId );
  2340. if (!UL_IS_VALID_HTTP_CONNECTION(pHttpConn))
  2341. {
  2342. status = STATUS_INVALID_PARAMETER;
  2343. goto end;
  2344. }
  2345. //
  2346. // Do it.
  2347. //
  2348. status = UlWaitForDisconnect(
  2349. GET_APP_POOL_PROCESS(pIrpSp->FileObject),
  2350. pHttpConn,
  2351. pIrp
  2352. );
  2353. end:
  2354. //
  2355. // Complete the request?
  2356. //
  2357. if (status != STATUS_PENDING)
  2358. {
  2359. pIrp->IoStatus.Status = status;
  2360. UlCompleteRequest( pIrp, g_UlPriorityBoost );
  2361. }
  2362. RETURN( status );
  2363. } // UlWaitForDisconnectIoctl
  2364. //
  2365. // Private functions.
  2366. //
  2367. /***************************************************************************++
  2368. Routine Description:
  2369. Completion routine for UlSendHttpResponse().
  2370. Arguments:
  2371. pCompletionContext - Supplies an uninterpreted context value
  2372. as passed to the asynchronous API. In this case, it's
  2373. actually a pointer to the user's IRP.
  2374. Status - Supplies the final completion status of the
  2375. asynchronous API.
  2376. Information - Optionally supplies additional information about
  2377. the completed operation, such as the number of bytes
  2378. transferred.
  2379. --***************************************************************************/
  2380. VOID
  2381. UlpRestartSendHttpResponse(
  2382. IN PVOID pCompletionContext,
  2383. IN NTSTATUS Status,
  2384. IN ULONG_PTR Information
  2385. )
  2386. {
  2387. PIRP pIrp;
  2388. PIO_STACK_LOCATION pIrpSp;
  2389. PUL_INTERNAL_RESPONSE pResponse;
  2390. //
  2391. // Snag the IRP from the completion context, fill in the completion
  2392. // status, then complete the IRP.
  2393. //
  2394. pIrp = (PIRP)pCompletionContext;
  2395. pIrpSp = IoGetCurrentIrpStackLocation( pIrp );
  2396. pResponse = (PUL_INTERNAL_RESPONSE)(
  2397. pIrpSp->Parameters.DeviceIoControl.Type3InputBuffer
  2398. );
  2399. ASSERT( UL_IS_VALID_INTERNAL_RESPONSE( pResponse ) );
  2400. UL_DEREFERENCE_INTERNAL_RESPONSE( pResponse );
  2401. //
  2402. // Only overwrite the status field if it hasn't already been set
  2403. // to an error
  2404. //
  2405. if (NT_SUCCESS(pIrp->IoStatus.Status))
  2406. pIrp->IoStatus.Status = Status;
  2407. pIrp->IoStatus.Information = Information;
  2408. UlCompleteRequest( pIrp, g_UlPriorityBoost );
  2409. } // UlpRestartSendHttpResponse
  2410. /***************************************************************************++
  2411. Routine Description:
  2412. This routine adds a new transient URL prefix.
  2413. Note: This is a METHOD_BUFFERED IOCTL.
  2414. Arguments:
  2415. pIrp - Supplies a pointer to the IO request packet.
  2416. pIrpSp - Supplies a pointer to the IO stack location to use for this
  2417. request.
  2418. Return Value:
  2419. NTSTATUS - Completion status.
  2420. --***************************************************************************/
  2421. NTSTATUS
  2422. UlAddTransientUrlIoctl(
  2423. IN PIRP pIrp,
  2424. IN PIO_STACK_LOCATION pIrpSp
  2425. )
  2426. {
  2427. NTSTATUS Status;
  2428. PHTTP_TRANSIENT_URL_INFO pInfo = NULL;
  2429. //
  2430. // sanity check.
  2431. //
  2432. PAGED_CODE();
  2433. // better be an application pool
  2434. //
  2435. if (IS_APP_POOL(pIrpSp->FileObject) == FALSE)
  2436. {
  2437. //
  2438. // Not an app pool.
  2439. //
  2440. Status = STATUS_INVALID_DEVICE_REQUEST;
  2441. goto end;
  2442. }
  2443. // Ensure the input buffer is large enough.
  2444. //
  2445. if (pIrpSp->Parameters.DeviceIoControl.InputBufferLength <
  2446. sizeof(HTTP_TRANSIENT_URL_INFO))
  2447. {
  2448. // bad buffer
  2449. //
  2450. Status = STATUS_BUFFER_TOO_SMALL;
  2451. goto end;
  2452. }
  2453. // Fetch out the input buffer
  2454. //
  2455. pInfo = (PHTTP_TRANSIENT_URL_INFO)pIrp->AssociatedIrp.SystemBuffer;
  2456. ASSERT(pInfo != NULL);
  2457. // does it look appropriate?
  2458. //
  2459. if (pInfo->FullyQualifiedUrl.MaximumLength < pInfo->FullyQualifiedUrl.Length ||
  2460. pInfo->FullyQualifiedUrl.Length == 0 ||
  2461. (pInfo->FullyQualifiedUrl.Length % sizeof(WCHAR)) != 0 ||
  2462. pInfo->FullyQualifiedUrl.Buffer == NULL)
  2463. {
  2464. Status = STATUS_INVALID_PARAMETER;
  2465. goto end;
  2466. }
  2467. // Going to access the url string from user mode memory
  2468. //
  2469. __try
  2470. {
  2471. // good memory?
  2472. //
  2473. ProbeTestForRead(pInfo->FullyQualifiedUrl.Buffer,
  2474. pInfo->FullyQualifiedUrl.Length + sizeof(WCHAR),
  2475. sizeof(WCHAR));
  2476. // must be null terminated
  2477. //
  2478. if (pInfo->FullyQualifiedUrl.Buffer[pInfo->FullyQualifiedUrl.Length/sizeof(WCHAR)] != UNICODE_NULL)
  2479. {
  2480. Status = STATUS_INVALID_PARAMETER;
  2481. __leave;
  2482. }
  2483. // CODEWORK: validate the incoming url.
  2484. //
  2485. // Call the internal worker func
  2486. //
  2487. Status = UlAddTransientUrl(
  2488. UlAppPoolObjectFromProcess(
  2489. GET_APP_POOL_PROCESS(pIrpSp->FileObject)
  2490. ),
  2491. &pInfo->FullyQualifiedUrl
  2492. );
  2493. if (!NT_SUCCESS(Status))
  2494. __leave;
  2495. }
  2496. __except( UL_EXCEPTION_FILTER() )
  2497. {
  2498. Status = UL_CONVERT_EXCEPTION_CODE(GetExceptionCode());
  2499. }
  2500. end:
  2501. // complete the request.
  2502. //
  2503. if (Status != STATUS_PENDING)
  2504. {
  2505. pIrp->IoStatus.Status = Status;
  2506. UlCompleteRequest( pIrp, g_UlPriorityBoost );
  2507. }
  2508. RETURN( Status );
  2509. } // UlAddTransientUrlIoctl
  2510. /***************************************************************************++
  2511. Routine Description:
  2512. This routine removes a transient URL prefix.
  2513. Note: This is a METHOD_BUFFERED IOCTL.
  2514. Arguments:
  2515. pIrp - Supplies a pointer to the IO request packet.
  2516. pIrpSp - Supplies a pointer to the IO stack location to use for this
  2517. request.
  2518. Return Value:
  2519. NTSTATUS - Completion status.
  2520. --***************************************************************************/
  2521. NTSTATUS
  2522. UlRemoveTransientUrlIoctl(
  2523. IN PIRP pIrp,
  2524. IN PIO_STACK_LOCATION pIrpSp
  2525. )
  2526. {
  2527. NTSTATUS Status;
  2528. PHTTP_TRANSIENT_URL_INFO pInfo = NULL;
  2529. //
  2530. // sanity check.
  2531. //
  2532. PAGED_CODE();
  2533. // better be an application pool
  2534. //
  2535. if (IS_APP_POOL(pIrpSp->FileObject) == FALSE)
  2536. {
  2537. //
  2538. // Not an app pool.
  2539. //
  2540. Status = STATUS_INVALID_DEVICE_REQUEST;
  2541. goto end;
  2542. }
  2543. // Ensure the input buffer is large enough.
  2544. //
  2545. if (pIrpSp->Parameters.DeviceIoControl.InputBufferLength <
  2546. sizeof(HTTP_TRANSIENT_URL_INFO))
  2547. {
  2548. // bad buffer
  2549. //
  2550. Status = STATUS_BUFFER_TOO_SMALL;
  2551. goto end;
  2552. }
  2553. // Fetch out the input buffer
  2554. //
  2555. pInfo = (PHTTP_TRANSIENT_URL_INFO)pIrp->AssociatedIrp.SystemBuffer;
  2556. ASSERT(pInfo != NULL);
  2557. // does it look appropriate?
  2558. //
  2559. if (pInfo->FullyQualifiedUrl.MaximumLength < pInfo->FullyQualifiedUrl.Length ||
  2560. pInfo->FullyQualifiedUrl.Length == 0 ||
  2561. (pInfo->FullyQualifiedUrl.Length % sizeof(WCHAR)) != 0 ||
  2562. pInfo->FullyQualifiedUrl.Buffer == NULL)
  2563. {
  2564. Status = STATUS_INVALID_PARAMETER;
  2565. goto end;
  2566. }
  2567. // Going to access the url string from user mode memory
  2568. //
  2569. __try
  2570. {
  2571. // good memory?
  2572. //
  2573. ProbeTestForRead(pInfo->FullyQualifiedUrl.Buffer,
  2574. pInfo->FullyQualifiedUrl.Length + sizeof(WCHAR),
  2575. sizeof(WCHAR));
  2576. // must be null terminated
  2577. //
  2578. if (pInfo->FullyQualifiedUrl.Buffer[pInfo->FullyQualifiedUrl.Length/sizeof(WCHAR)] != UNICODE_NULL)
  2579. {
  2580. Status = STATUS_INVALID_PARAMETER;
  2581. __leave;
  2582. }
  2583. // CODEWORK: validate the incoming url.
  2584. //
  2585. // Call the internal worker func
  2586. //
  2587. Status = UlRemoveTransientUrl(
  2588. UlAppPoolObjectFromProcess(
  2589. GET_APP_POOL_PROCESS(pIrpSp->FileObject)
  2590. ),
  2591. &pInfo->FullyQualifiedUrl
  2592. );
  2593. if (!NT_SUCCESS(Status))
  2594. __leave;
  2595. }
  2596. __except( UL_EXCEPTION_FILTER() )
  2597. {
  2598. Status = UL_CONVERT_EXCEPTION_CODE(GetExceptionCode());
  2599. }
  2600. end:
  2601. // complete the request.
  2602. //
  2603. if (Status != STATUS_PENDING)
  2604. {
  2605. pIrp->IoStatus.Status = Status;
  2606. UlCompleteRequest( pIrp, g_UlPriorityBoost );
  2607. }
  2608. RETURN( Status );
  2609. } // UlRemoveTransientUrlIoctl
  2610. /***************************************************************************++
  2611. Routine Description:
  2612. This routine accepts a raw connection.
  2613. Note: This is a METHOD_OUT_DIRECT IOCTL.
  2614. Arguments:
  2615. pIrp - Supplies a pointer to the IO request packet.
  2616. pIrpSp - Supplies a pointer to the IO stack location to use for this
  2617. request.
  2618. Return Value:
  2619. NTSTATUS - Completion status.
  2620. --***************************************************************************/
  2621. NTSTATUS
  2622. UlFilterAcceptIoctl(
  2623. IN PIRP pIrp,
  2624. IN PIO_STACK_LOCATION pIrpSp
  2625. )
  2626. {
  2627. NTSTATUS Status;
  2628. //
  2629. // Sanity check.
  2630. //
  2631. PAGED_CODE();
  2632. //
  2633. // This had better be a filter channel.
  2634. //
  2635. if (!IS_FILTER_PROCESS(pIrpSp->FileObject))
  2636. {
  2637. //
  2638. // Not a filter channel.
  2639. //
  2640. Status = STATUS_INVALID_DEVICE_REQUEST;
  2641. goto end;
  2642. }
  2643. //
  2644. // make the call
  2645. //
  2646. Status = UlFilterAccept(
  2647. GET_FILTER_PROCESS(pIrpSp->FileObject),
  2648. pIrp
  2649. );
  2650. end:
  2651. //
  2652. // complete the request?
  2653. //
  2654. if (Status != STATUS_PENDING)
  2655. {
  2656. pIrp->IoStatus.Status = Status;
  2657. UlCompleteRequest( pIrp, g_UlPriorityBoost );
  2658. }
  2659. RETURN( Status );
  2660. } // UlFilterAcceptIoctl
  2661. /***************************************************************************++
  2662. Routine Description:
  2663. This routine closes a raw connection.
  2664. Note: This is a METHOD_BUFFERED IOCTL.
  2665. Arguments:
  2666. pIrp - Supplies a pointer to the IO request packet.
  2667. pIrpSp - Supplies a pointer to the IO stack location to use for this
  2668. request.
  2669. Return Value:
  2670. NTSTATUS - Completion status.
  2671. --***************************************************************************/
  2672. NTSTATUS
  2673. UlFilterCloseIoctl(
  2674. IN PIRP pIrp,
  2675. IN PIO_STACK_LOCATION pIrpSp
  2676. )
  2677. {
  2678. NTSTATUS Status;
  2679. HTTP_RAW_CONNECTION_ID ConnectionId;
  2680. PUX_FILTER_CONNECTION pConnection;
  2681. //
  2682. // Sanity check.
  2683. //
  2684. PAGED_CODE();
  2685. //
  2686. // Set up locals so we know how to clean up on exit.
  2687. //
  2688. pConnection = NULL;
  2689. //
  2690. // This had better be a filter channel.
  2691. //
  2692. if (!IS_FILTER_PROCESS(pIrpSp->FileObject))
  2693. {
  2694. //
  2695. // Not a filter channel.
  2696. //
  2697. Status = STATUS_INVALID_DEVICE_REQUEST;
  2698. goto end;
  2699. }
  2700. //
  2701. // Ensure the input buffer is large enough.
  2702. //
  2703. if (pIrpSp->Parameters.DeviceIoControl.InputBufferLength <
  2704. sizeof(ConnectionId))
  2705. {
  2706. //
  2707. // Input buffer too small.
  2708. //
  2709. Status = STATUS_BUFFER_TOO_SMALL;
  2710. goto end;
  2711. }
  2712. //
  2713. // Map the incoming connection ID to the corresponding
  2714. // UX_FILTER_CONNECTION object.
  2715. //
  2716. ConnectionId = *((PHTTP_RAW_CONNECTION_ID)pIrp->AssociatedIrp.SystemBuffer);
  2717. pConnection = UlGetRawConnectionFromId(ConnectionId);
  2718. if (!pConnection)
  2719. {
  2720. Status = STATUS_INVALID_PARAMETER;
  2721. goto end;
  2722. }
  2723. ASSERT(IS_VALID_FILTER_CONNECTION(pConnection));
  2724. //
  2725. // make the call
  2726. //
  2727. Status = UlFilterClose(
  2728. GET_FILTER_PROCESS(pIrpSp->FileObject),
  2729. pConnection,
  2730. pIrp
  2731. );
  2732. end:
  2733. if (pConnection)
  2734. {
  2735. DEREFERENCE_FILTER_CONNECTION(pConnection);
  2736. }
  2737. //
  2738. // complete the request?
  2739. //
  2740. if (Status != STATUS_PENDING)
  2741. {
  2742. pIrp->IoStatus.Status = Status;
  2743. UlCompleteRequest( pIrp, g_UlPriorityBoost );
  2744. }
  2745. RETURN( Status );
  2746. } // UlFilterCloseIoctl
  2747. /***************************************************************************++
  2748. Routine Description:
  2749. This routine reads data from a raw connection.
  2750. Note: This is a METHOD_OUT_DIRECT IOCTL.
  2751. Arguments:
  2752. pIrp - Supplies a pointer to the IO request packet.
  2753. pIrpSp - Supplies a pointer to the IO stack location to use for this
  2754. request.
  2755. Return Value:
  2756. NTSTATUS - Completion status.
  2757. --***************************************************************************/
  2758. NTSTATUS
  2759. UlFilterRawReadIoctl(
  2760. IN PIRP pIrp,
  2761. IN PIO_STACK_LOCATION pIrpSp
  2762. )
  2763. {
  2764. NTSTATUS Status;
  2765. HTTP_RAW_CONNECTION_ID ConnectionId;
  2766. PUX_FILTER_CONNECTION pConnection;
  2767. //
  2768. // Sanity check.
  2769. //
  2770. PAGED_CODE();
  2771. //
  2772. // Set up locals so we know how to clean up on exit.
  2773. //
  2774. pConnection = NULL;
  2775. //
  2776. // This had better be a filter channel.
  2777. //
  2778. if (!IS_FILTER_PROCESS(pIrpSp->FileObject))
  2779. {
  2780. //
  2781. // Not a filter channel.
  2782. //
  2783. Status = STATUS_INVALID_DEVICE_REQUEST;
  2784. goto end;
  2785. }
  2786. //
  2787. // Ensure the input buffer is large enough.
  2788. //
  2789. if (pIrpSp->Parameters.DeviceIoControl.InputBufferLength <
  2790. sizeof(ConnectionId))
  2791. {
  2792. //
  2793. // Input buffer too small.
  2794. //
  2795. Status = STATUS_BUFFER_TOO_SMALL;
  2796. goto end;
  2797. }
  2798. //
  2799. // Map the incoming connection ID to the corresponding
  2800. // UX_FILTER_CONNECTION object.
  2801. //
  2802. ConnectionId = *((PHTTP_RAW_CONNECTION_ID)pIrp->AssociatedIrp.SystemBuffer);
  2803. pConnection = UlGetRawConnectionFromId(ConnectionId);
  2804. if (!pConnection)
  2805. {
  2806. Status = STATUS_INVALID_PARAMETER;
  2807. goto end;
  2808. }
  2809. ASSERT(IS_VALID_FILTER_CONNECTION(pConnection));
  2810. //
  2811. // make the call
  2812. //
  2813. Status = UlFilterRawRead(
  2814. GET_FILTER_PROCESS(pIrpSp->FileObject),
  2815. pConnection,
  2816. pIrp
  2817. );
  2818. end:
  2819. if (pConnection)
  2820. {
  2821. DEREFERENCE_FILTER_CONNECTION(pConnection);
  2822. }
  2823. //
  2824. // complete the request?
  2825. //
  2826. if (Status != STATUS_PENDING)
  2827. {
  2828. pIrp->IoStatus.Status = Status;
  2829. UlCompleteRequest( pIrp, g_UlPriorityBoost );
  2830. }
  2831. RETURN( Status );
  2832. } // UlFilterRawReadIoctl
  2833. /***************************************************************************++
  2834. Routine Description:
  2835. This routine writes data to a raw connection.
  2836. Note: This is a METHOD_IN_DIRECT IOCTL.
  2837. Arguments:
  2838. pIrp - Supplies a pointer to the IO request packet.
  2839. pIrpSp - Supplies a pointer to the IO stack location to use for this
  2840. request.
  2841. Return Value:
  2842. NTSTATUS - Completion status.
  2843. --***************************************************************************/
  2844. NTSTATUS
  2845. UlFilterRawWriteIoctl(
  2846. IN PIRP pIrp,
  2847. IN PIO_STACK_LOCATION pIrpSp
  2848. )
  2849. {
  2850. NTSTATUS Status;
  2851. HTTP_RAW_CONNECTION_ID ConnectionId;
  2852. PUX_FILTER_CONNECTION pConnection;
  2853. BOOLEAN MarkedPending;
  2854. //
  2855. // Sanity check.
  2856. //
  2857. PAGED_CODE();
  2858. //
  2859. // Set up locals so we know how to clean up on exit.
  2860. //
  2861. pConnection = NULL;
  2862. MarkedPending = FALSE;
  2863. //
  2864. // This had better be a filter channel.
  2865. //
  2866. if (!IS_FILTER_PROCESS(pIrpSp->FileObject))
  2867. {
  2868. //
  2869. // Not a filter channel.
  2870. //
  2871. Status = STATUS_INVALID_DEVICE_REQUEST;
  2872. goto end;
  2873. }
  2874. //
  2875. // Ensure the input buffer is large enough.
  2876. //
  2877. if (pIrpSp->Parameters.DeviceIoControl.InputBufferLength <
  2878. sizeof(ConnectionId))
  2879. {
  2880. //
  2881. // Input buffer too small.
  2882. //
  2883. Status = STATUS_BUFFER_TOO_SMALL;
  2884. goto end;
  2885. }
  2886. //
  2887. // Ensure that there's an output buffer.
  2888. //
  2889. if (!pIrp->MdlAddress)
  2890. {
  2891. Status = STATUS_INVALID_PARAMETER;
  2892. goto end;
  2893. }
  2894. //
  2895. // Map the incoming connection ID to the corresponding
  2896. // UX_FILTER_CONNECTION object.
  2897. //
  2898. ConnectionId = *((PHTTP_RAW_CONNECTION_ID)pIrp->AssociatedIrp.SystemBuffer);
  2899. pConnection = UlGetRawConnectionFromId(ConnectionId);
  2900. if (!pConnection)
  2901. {
  2902. Status = STATUS_INVALID_PARAMETER;
  2903. goto end;
  2904. }
  2905. ASSERT(IS_VALID_FILTER_CONNECTION(pConnection));
  2906. //
  2907. // make the call
  2908. //
  2909. IoMarkIrpPending(pIrp);
  2910. MarkedPending = TRUE;
  2911. Status = UlFilterRawWrite(
  2912. GET_FILTER_PROCESS(pIrpSp->FileObject),
  2913. pConnection,
  2914. pIrpSp->Parameters.DeviceIoControl.OutputBufferLength,
  2915. pIrp
  2916. );
  2917. end:
  2918. if (pConnection)
  2919. {
  2920. DEREFERENCE_FILTER_CONNECTION(pConnection);
  2921. }
  2922. //
  2923. // complete the request?
  2924. //
  2925. if (Status != STATUS_PENDING)
  2926. {
  2927. pIrp->IoStatus.Status = Status;
  2928. UlCompleteRequest( pIrp, g_UlPriorityBoost );
  2929. if (MarkedPending)
  2930. {
  2931. //
  2932. // Since we marked the IRP pending, we should return pending.
  2933. //
  2934. Status = STATUS_PENDING;
  2935. }
  2936. }
  2937. else
  2938. {
  2939. //
  2940. // If we're returning pending, the IRP better be marked pending.
  2941. //
  2942. ASSERT(MarkedPending);
  2943. }
  2944. RETURN( Status );
  2945. } // UlFilterRawWriteIoctl
  2946. /***************************************************************************++
  2947. Routine Description:
  2948. This routine reads data from an http application.
  2949. Note: This is a METHOD_OUT_DIRECT IOCTL.
  2950. Arguments:
  2951. pIrp - Supplies a pointer to the IO request packet.
  2952. pIrpSp - Supplies a pointer to the IO stack location to use for this
  2953. request.
  2954. Return Value:
  2955. NTSTATUS - Completion status.
  2956. --***************************************************************************/
  2957. NTSTATUS
  2958. UlFilterAppReadIoctl(
  2959. IN PIRP pIrp,
  2960. IN PIO_STACK_LOCATION pIrpSp
  2961. )
  2962. {
  2963. NTSTATUS Status;
  2964. HTTP_RAW_CONNECTION_ID ConnectionId;
  2965. PUX_FILTER_CONNECTION pConnection;
  2966. PHTTP_FILTER_BUFFER pFiltBuffer;
  2967. //
  2968. // Sanity check.
  2969. //
  2970. PAGED_CODE();
  2971. //
  2972. // Set up locals so we know how to clean up on exit.
  2973. //
  2974. pConnection = NULL;
  2975. //
  2976. // This had better be a filter channel.
  2977. //
  2978. if (!IS_FILTER_PROCESS(pIrpSp->FileObject))
  2979. {
  2980. //
  2981. // Not a filter channel.
  2982. //
  2983. Status = STATUS_INVALID_DEVICE_REQUEST;
  2984. goto end;
  2985. }
  2986. //
  2987. // Ensure the input buffer is large enough.
  2988. //
  2989. if (pIrpSp->Parameters.DeviceIoControl.InputBufferLength <
  2990. sizeof(HTTP_FILTER_BUFFER))
  2991. {
  2992. //
  2993. // Input buffer too small.
  2994. //
  2995. Status = STATUS_BUFFER_TOO_SMALL;
  2996. goto end;
  2997. }
  2998. //
  2999. // Ensure the output buffer is large enough.
  3000. //
  3001. if (pIrpSp->Parameters.DeviceIoControl.OutputBufferLength <
  3002. sizeof(HTTP_FILTER_BUFFER))
  3003. {
  3004. //
  3005. // Output buffer too small.
  3006. //
  3007. Status = STATUS_BUFFER_TOO_SMALL;
  3008. goto end;
  3009. }
  3010. //
  3011. // Grab the filter buffer object.
  3012. //
  3013. pFiltBuffer = (PHTTP_FILTER_BUFFER) pIrp->AssociatedIrp.SystemBuffer;
  3014. //
  3015. // Map the incoming connection ID to the corresponding
  3016. // UX_FILTER_CONNECTION object.
  3017. //
  3018. ConnectionId = pFiltBuffer->Reserved;
  3019. pConnection = UlGetRawConnectionFromId(ConnectionId);
  3020. if (!pConnection)
  3021. {
  3022. Status = STATUS_INVALID_PARAMETER;
  3023. goto end;
  3024. }
  3025. ASSERT(IS_VALID_FILTER_CONNECTION(pConnection));
  3026. //
  3027. // make the call
  3028. //
  3029. Status = UlFilterAppRead(
  3030. GET_FILTER_PROCESS(pIrpSp->FileObject),
  3031. pConnection,
  3032. pIrp
  3033. );
  3034. end:
  3035. if (pConnection)
  3036. {
  3037. DEREFERENCE_FILTER_CONNECTION(pConnection);
  3038. }
  3039. //
  3040. // complete the request?
  3041. //
  3042. if (Status != STATUS_PENDING)
  3043. {
  3044. pIrp->IoStatus.Status = Status;
  3045. UlCompleteRequest( pIrp, g_UlPriorityBoost );
  3046. }
  3047. RETURN( Status );
  3048. } // UlFilterAppReadIoctl
  3049. /***************************************************************************++
  3050. Routine Description:
  3051. This routine writes data to an http application.
  3052. Note: This is a METHOD_IN_DIRECT IOCTL.
  3053. Arguments:
  3054. pIrp - Supplies a pointer to the IO request packet.
  3055. pIrpSp - Supplies a pointer to the IO stack location to use for this
  3056. request.
  3057. Return Value:
  3058. NTSTATUS - Completion status.
  3059. --***************************************************************************/
  3060. NTSTATUS
  3061. UlFilterAppWriteIoctl(
  3062. IN PIRP pIrp,
  3063. IN PIO_STACK_LOCATION pIrpSp
  3064. )
  3065. {
  3066. NTSTATUS Status;
  3067. HTTP_RAW_CONNECTION_ID ConnectionId;
  3068. PUX_FILTER_CONNECTION pConnection;
  3069. BOOLEAN MarkedPending;
  3070. PHTTP_FILTER_BUFFER pFiltBuffer;
  3071. //
  3072. // Sanity check.
  3073. //
  3074. PAGED_CODE();
  3075. //
  3076. // Set up locals so we know how to clean up on exit.
  3077. //
  3078. pConnection = NULL;
  3079. MarkedPending = FALSE;
  3080. //
  3081. // This had better be a filter channel.
  3082. //
  3083. if (!IS_FILTER_PROCESS(pIrpSp->FileObject))
  3084. {
  3085. //
  3086. // Not a filter channel.
  3087. //
  3088. Status = STATUS_INVALID_DEVICE_REQUEST;
  3089. goto end;
  3090. }
  3091. //
  3092. // Ensure the input buffer is large enough.
  3093. //
  3094. if (pIrpSp->Parameters.DeviceIoControl.InputBufferLength <
  3095. sizeof(HTTP_FILTER_BUFFER))
  3096. {
  3097. //
  3098. // Input buffer too small.
  3099. //
  3100. Status = STATUS_BUFFER_TOO_SMALL;
  3101. goto end;
  3102. }
  3103. //
  3104. // Grab the filter buffer object.
  3105. //
  3106. pFiltBuffer = (PHTTP_FILTER_BUFFER) pIrp->AssociatedIrp.SystemBuffer;
  3107. //
  3108. // Map the incoming connection ID to the corresponding
  3109. // UX_FILTER_CONNECTION object.
  3110. //
  3111. ConnectionId = pFiltBuffer->Reserved;
  3112. pConnection = UlGetRawConnectionFromId(ConnectionId);
  3113. if (!pConnection)
  3114. {
  3115. Status = STATUS_INVALID_PARAMETER;
  3116. goto end;
  3117. }
  3118. ASSERT(IS_VALID_FILTER_CONNECTION(pConnection));
  3119. //
  3120. // make the call
  3121. //
  3122. IoMarkIrpPending(pIrp);
  3123. MarkedPending = TRUE;
  3124. Status = UlFilterAppWrite(
  3125. GET_FILTER_PROCESS(pIrpSp->FileObject),
  3126. pConnection,
  3127. pIrp
  3128. );
  3129. end:
  3130. if (pConnection)
  3131. {
  3132. DEREFERENCE_FILTER_CONNECTION(pConnection);
  3133. }
  3134. //
  3135. // complete the request?
  3136. //
  3137. if (Status != STATUS_PENDING)
  3138. {
  3139. pIrp->IoStatus.Status = Status;
  3140. UlCompleteRequest( pIrp, g_UlPriorityBoost );
  3141. if (MarkedPending)
  3142. {
  3143. //
  3144. // Since we marked the IRP pending, we should return pending.
  3145. //
  3146. Status = STATUS_PENDING;
  3147. }
  3148. }
  3149. else
  3150. {
  3151. //
  3152. // If we're returning pending, the IRP better be marked pending.
  3153. //
  3154. ASSERT(MarkedPending);
  3155. }
  3156. RETURN( Status );
  3157. } // UlFilterAppWriteIoctl
  3158. /***************************************************************************++
  3159. Routine Description:
  3160. This routine asks the SSL helper for a client certificate.
  3161. Note: This is a METHOD_OUT_DIRECT IOCTL.
  3162. Arguments:
  3163. pIrp - Supplies a pointer to the IO request packet.
  3164. pIrpSp - Supplies a pointer to the IO stack location to use for this
  3165. request.
  3166. Return Value:
  3167. NTSTATUS - Completion status.
  3168. --***************************************************************************/
  3169. NTSTATUS
  3170. UlReceiveClientCertIoctl(
  3171. IN PIRP pIrp,
  3172. IN PIO_STACK_LOCATION pIrpSp
  3173. )
  3174. {
  3175. NTSTATUS Status;
  3176. PHTTP_FILTER_RECEIVE_CLIENT_CERT_INFO pReceiveCertInfo;
  3177. HTTP_RAW_CONNECTION_ID ConnectionId;
  3178. PUL_HTTP_CONNECTION pHttpConn;
  3179. //
  3180. // Sanity check.
  3181. //
  3182. PAGED_CODE();
  3183. //
  3184. // Set up locals so we know how to clean up on exit.
  3185. //
  3186. pHttpConn = NULL;
  3187. //
  3188. // This had better be an app pool.
  3189. //
  3190. if (IS_APP_POOL(pIrpSp->FileObject) == FALSE)
  3191. {
  3192. //
  3193. // Not an app pool.
  3194. //
  3195. Status = STATUS_INVALID_DEVICE_REQUEST;
  3196. goto end;
  3197. }
  3198. //
  3199. // Ensure the input buffer is large enough.
  3200. //
  3201. if (pIrpSp->Parameters.DeviceIoControl.InputBufferLength <
  3202. sizeof(HTTP_FILTER_RECEIVE_CLIENT_CERT_INFO))
  3203. {
  3204. //
  3205. // Input buffer too small.
  3206. //
  3207. Status = STATUS_BUFFER_TOO_SMALL;
  3208. goto end;
  3209. }
  3210. //
  3211. // Ensure the output buffer is large enough.
  3212. //
  3213. if (pIrpSp->Parameters.DeviceIoControl.OutputBufferLength <
  3214. sizeof(HTTP_SSL_CLIENT_CERT_INFO))
  3215. {
  3216. //
  3217. // Output buffer too small.
  3218. //
  3219. Status = STATUS_BUFFER_TOO_SMALL;
  3220. goto end;
  3221. }
  3222. //
  3223. // Grab the cert receive object.
  3224. //
  3225. pReceiveCertInfo = (PHTTP_FILTER_RECEIVE_CLIENT_CERT_INFO)
  3226. pIrp->AssociatedIrp.SystemBuffer;
  3227. //
  3228. // Map the incoming connection ID to the corresponding
  3229. // HTTP_CONNECTION object.
  3230. //
  3231. ConnectionId = pReceiveCertInfo->ConnectionId;
  3232. pHttpConn = UlGetConnectionFromId(ConnectionId);
  3233. if (!pHttpConn)
  3234. {
  3235. Status = STATUS_INVALID_PARAMETER;
  3236. goto end;
  3237. }
  3238. ASSERT(UL_IS_VALID_HTTP_CONNECTION(pHttpConn));
  3239. //
  3240. // make the call
  3241. //
  3242. Status = UlReceiveClientCert(
  3243. GET_APP_POOL_PROCESS(pIrpSp->FileObject),
  3244. &pHttpConn->pConnection->FilterInfo,
  3245. pReceiveCertInfo->Flags,
  3246. pIrp
  3247. );
  3248. end:
  3249. if (pHttpConn)
  3250. {
  3251. UL_DEREFERENCE_HTTP_CONNECTION(pHttpConn);
  3252. }
  3253. //
  3254. // complete the request?
  3255. //
  3256. if (Status != STATUS_PENDING)
  3257. {
  3258. pIrp->IoStatus.Status = Status;
  3259. UlCompleteRequest( pIrp, g_UlPriorityBoost );
  3260. }
  3261. RETURN( Status );
  3262. } // UlFilterReceiveClientCertIoctl
  3263. /***************************************************************************++
  3264. Routine Description:
  3265. This routine returns the perfmon counter data for this driver
  3266. Note: This is a METHOD_OUT_DIRECT IOCTL.
  3267. Arguments:
  3268. pIrp - Supplies a pointer to the IO request packet.
  3269. pIrpSp - Supplies a pointer to the IO stack location to use for this
  3270. request.
  3271. Return Value:
  3272. NTSTATUS - Completion status.
  3273. --***************************************************************************/
  3274. NTSTATUS
  3275. UlGetCountersIoctl(
  3276. IN PIRP pIrp,
  3277. IN PIO_STACK_LOCATION pIrpSp
  3278. )
  3279. {
  3280. NTSTATUS Status;
  3281. PUL_CONTROL_CHANNEL pControlChannel;
  3282. ULONG Length;
  3283. PVOID pMdlBuffer;
  3284. PVOID pMdlVa;
  3285. HTTP_COUNTER_GROUP CounterGroup;
  3286. //
  3287. // Sanity check.
  3288. //
  3289. PAGED_CODE();
  3290. //
  3291. // Set up locals so we know how to clean up on exit.
  3292. //
  3293. Status = STATUS_SUCCESS;
  3294. Length = pIrpSp->Parameters.DeviceIoControl.OutputBufferLength;
  3295. //
  3296. // better be a control channel
  3297. //
  3298. if (IS_CONTROL_CHANNEL(pIrpSp->FileObject) == FALSE)
  3299. {
  3300. //
  3301. // Not a control channel.
  3302. //
  3303. Status = STATUS_INVALID_DEVICE_REQUEST;
  3304. goto End;
  3305. }
  3306. pControlChannel = GET_CONTROL_CHANNEL(pIrpSp->FileObject);
  3307. if (IS_VALID_CONTROL_CHANNEL(pControlChannel) == FALSE)
  3308. {
  3309. Status = STATUS_INVALID_PARAMETER;
  3310. goto End;
  3311. }
  3312. //
  3313. // Find out which type of counters are requested
  3314. //
  3315. if (pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(HTTP_COUNTER_GROUP))
  3316. {
  3317. Status = STATUS_INVALID_PARAMETER;
  3318. goto End;
  3319. }
  3320. CounterGroup = *((HTTP_COUNTER_GROUP *) pIrp->AssociatedIrp.SystemBuffer);
  3321. // Crack IRP and get MDL contianing user's buffer
  3322. // Crack MDL to get user's buffer
  3323. __try
  3324. {
  3325. // if no outbut buffer pass down in the Irp
  3326. // that means app is asking for the required
  3327. // field length
  3328. if (!pIrp->MdlAddress)
  3329. {
  3330. pMdlVa = NULL;
  3331. }
  3332. else
  3333. {
  3334. pMdlBuffer = MmGetSystemAddressForMdlSafe(
  3335. pIrp->MdlAddress,
  3336. LowPagePriority
  3337. );
  3338. if (pMdlBuffer == NULL)
  3339. {
  3340. Status = STATUS_INSUFFICIENT_RESOURCES;
  3341. __leave;
  3342. }
  3343. // Also make sure that user buffer was good
  3344. pMdlVa = MmGetMdlVirtualAddress(pIrp->MdlAddress);
  3345. ProbeForWrite( pMdlVa,
  3346. Length,
  3347. sizeof(UCHAR) );
  3348. }
  3349. //
  3350. // Call support function to gather apropriate counter blocks
  3351. // and place in user's buffer.
  3352. //
  3353. if ( HttpCounterGroupGlobal == CounterGroup )
  3354. {
  3355. Status = UlGetGlobalCounters(
  3356. pMdlVa,
  3357. Length,
  3358. &Length
  3359. );
  3360. }
  3361. else if ( HttpCounterGroupSite == CounterGroup )
  3362. {
  3363. ULONG Blocks;
  3364. Status = UlGetSiteCounters(
  3365. pMdlVa,
  3366. Length,
  3367. &Length,
  3368. &Blocks
  3369. );
  3370. }
  3371. else
  3372. {
  3373. Status = STATUS_NOT_IMPLEMENTED;
  3374. __leave;
  3375. }
  3376. if (!NT_SUCCESS(Status))
  3377. {
  3378. //
  3379. // If not returning STATUS_SUCCESS,
  3380. // IoStatus.Information *must* be 0.
  3381. //
  3382. pIrp->IoStatus.Information = 0;
  3383. __leave;
  3384. }
  3385. else
  3386. {
  3387. pIrp->IoStatus.Information = (ULONG_PTR)Length;
  3388. }
  3389. }
  3390. __except( UL_EXCEPTION_FILTER() )
  3391. {
  3392. Status = UL_CONVERT_EXCEPTION_CODE(GetExceptionCode());
  3393. pIrp->IoStatus.Information = 0;
  3394. }
  3395. End:
  3396. //
  3397. // complete the request?
  3398. //
  3399. if (Status != STATUS_PENDING)
  3400. {
  3401. pIrp->IoStatus.Status = Status;
  3402. UlCompleteRequest( pIrp, g_UlPriorityBoost );
  3403. }
  3404. RETURN( Status );
  3405. } // UlGetCountersIoctl