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.

845 lines
17 KiB

  1. /*++
  2. Copyright (c) 1998-2001 Microsoft Corporation
  3. Module Name:
  4. sendresponse.h
  5. Abstract:
  6. This module contains declarations for manipulating HTTP responses.
  7. Author:
  8. Keith Moore (keithmo) 07-Aug-1998
  9. Revision History:
  10. Paul McDaniel (paulmcd) 15-Mar-1999 Modified SendResponse
  11. --*/
  12. #ifndef _SENDRESPONSE_H_
  13. #define _SENDRESPONSE_H_
  14. #ifdef __cplusplus
  15. extern "C" {
  16. #endif
  17. //
  18. // Forwarders.
  19. //
  20. typedef struct _UL_INTERNAL_DATA_CHUNK *PUL_INTERNAL_DATA_CHUNK;
  21. typedef struct _UL_INTERNAL_REQUEST *PUL_INTERNAL_REQUEST;
  22. typedef struct _UL_INTERNAL_RESPONSE *PUL_INTERNAL_RESPONSE;
  23. typedef struct _UL_HTTP_CONNECTION *PUL_HTTP_CONNECTION;
  24. typedef struct _UL_LOG_DATA_BUFFER *PUL_LOG_DATA_BUFFER;
  25. typedef struct _UL_URI_CACHE_ENTRY *PUL_URI_CACHE_ENTRY;
  26. NTSTATUS
  27. UlSendHttpResponse(
  28. IN PUL_INTERNAL_REQUEST pRequest,
  29. IN PUL_INTERNAL_RESPONSE pResponse,
  30. IN ULONG Flags,
  31. IN PUL_COMPLETION_ROUTINE pCompletionRoutine,
  32. IN PVOID pCompletionContext
  33. );
  34. NTSTATUS
  35. UlSendCachedResponse(
  36. PUL_HTTP_CONNECTION pHttpConn,
  37. PBOOLEAN pServedFromCache,
  38. PBOOLEAN pConnectionRefused
  39. );
  40. NTSTATUS
  41. UlCacheAndSendResponse(
  42. IN PUL_INTERNAL_REQUEST pRequest,
  43. IN PUL_INTERNAL_RESPONSE pResponse,
  44. IN PUL_APP_POOL_PROCESS pProcess,
  45. IN ULONG Flags,
  46. IN HTTP_CACHE_POLICY Policy,
  47. IN PUL_COMPLETION_ROUTINE pCompletionRoutine,
  48. IN PVOID pCompletionContext,
  49. OUT PBOOLEAN pServedFromCache
  50. );
  51. typedef enum _UL_CAPTURE_FLAGS
  52. {
  53. UlCaptureNothing = 0x00,
  54. UlCaptureCopyData = 0x01,
  55. UlCaptureKernelMode = 0x02,
  56. UlCaptureCopyDataInKernelMode = UlCaptureCopyData | UlCaptureKernelMode,
  57. } UL_CAPTURE_FLAGS;
  58. typedef struct _UL_INTERNAL_DATA_CHUNK
  59. {
  60. //
  61. // Chunk type.
  62. //
  63. HTTP_DATA_CHUNK_TYPE ChunkType;
  64. //
  65. // The data chunk structures, one per supported data chunk type.
  66. //
  67. union
  68. {
  69. //
  70. // From memory data chunk.
  71. //
  72. struct
  73. {
  74. PMDL pMdl;
  75. PVOID pCopiedBuffer;
  76. PVOID pUserBuffer;
  77. ULONG BufferLength;
  78. } FromMemory;
  79. //
  80. // From filename data chunk.
  81. //
  82. struct
  83. {
  84. HTTP_BYTE_RANGE ByteRange;
  85. union
  86. {
  87. UNICODE_STRING FileName;
  88. HANDLE FileHandle;
  89. };
  90. PUL_FILE_CACHE_ENTRY pFileCacheEntry;
  91. } FromFile;
  92. };
  93. } UL_INTERNAL_DATA_CHUNK, *PUL_INTERNAL_DATA_CHUNK;
  94. #define IS_FROM_MEMORY( pchunk ) \
  95. ( (pchunk)->ChunkType == HttpDataChunkFromMemory )
  96. #define IS_FROM_FILE( pchunk ) \
  97. ( (pchunk)->ChunkType == HttpDataChunkFromFileName || \
  98. (pchunk)->ChunkType == HttpDataChunkFromFileHandle )
  99. #define IS_FROM_FILE_NAME( pchunk ) \
  100. ( (pchunk)->ChunkType == HttpDataChunkFromFileName )
  101. #define IS_FROM_FILE_HANDLE( pchunk ) \
  102. ( (pchunk)->ChunkType == HttpDataChunkFromFileHandle )
  103. #define UL_IS_VALID_INTERNAL_RESPONSE(x) \
  104. ( (x) != NULL && (x)->Signature == UL_INTERNAL_RESPONSE_POOL_TAG )
  105. //
  106. // WARNING! All fields of this structure must be explicitly initialized.
  107. //
  108. typedef struct _UL_INTERNAL_RESPONSE
  109. {
  110. //
  111. // NonPagedPool
  112. //
  113. //
  114. // This MUST be the first field in the structure. This is the linkage
  115. // used by the lookaside package for storing entries in the lookaside
  116. // list.
  117. //
  118. SINGLE_LIST_ENTRY LookasideEntry;
  119. //
  120. // UL_INTERNAL_RESPONSE_POOL_TAG
  121. //
  122. ULONG Signature;
  123. //
  124. // Reference count.
  125. //
  126. LONG ReferenceCount;
  127. //
  128. // SendBufferedBytes for this response.
  129. //
  130. LONG SendBufferedBytes;
  131. //
  132. // Is it ok to complete the IRP as soon as we capture
  133. // the response?
  134. //
  135. BOOLEAN CompleteIrpEarly;
  136. //
  137. // Was a Content-Length specified?
  138. //
  139. BOOLEAN ContentLengthSpecified;
  140. //
  141. // Was Transfer-Encoding "Chunked" specified?
  142. //
  143. BOOLEAN ChunkedSpecified;
  144. //
  145. // Is this from a lookaside list? Used to determine how to free.
  146. //
  147. BOOLEAN IsFromLookaside;
  148. //
  149. // Status code & verb.
  150. //
  151. USHORT StatusCode;
  152. HTTP_VERB Verb;
  153. //
  154. // The headers.
  155. //
  156. ULONG HeaderLength;
  157. PUCHAR pHeaders;
  158. //
  159. // System time of Date header
  160. //
  161. LARGE_INTEGER CreationTime;
  162. //
  163. // ETag from HTTP_RESPONSE
  164. //
  165. ULONG ETagLength;
  166. PUCHAR pETag;
  167. //
  168. // Content-Type from HTTP_RESPONSE
  169. //
  170. UL_CONTENT_TYPE ContentType;
  171. //
  172. // Optional pointer to the space containing all embedded
  173. // file names and copied data. This may be NULL for in-memory-only
  174. // responses that are strictly locked down.
  175. //
  176. ULONG AuxBufferLength;
  177. PVOID pAuxiliaryBuffer;
  178. //
  179. // The maximum IRP stack size of all file systems associated
  180. // with this response.
  181. //
  182. union
  183. {
  184. CCHAR MaxFileSystemStackSize;
  185. PVOID Alignment1;
  186. };
  187. //
  188. // Logging data passed down by the user
  189. //
  190. PUL_LOG_DATA_BUFFER pLogData;
  191. //
  192. // Length of the entire response
  193. //
  194. ULONGLONG ResponseLength;
  195. //
  196. // The total number of chunks in pDataChunks[].
  197. //
  198. ULONG ChunkCount;
  199. //
  200. // The data chunks describing the data for this response.
  201. //
  202. UL_INTERNAL_DATA_CHUNK pDataChunks[0];
  203. } UL_INTERNAL_RESPONSE, *PUL_INTERNAL_RESPONSE;
  204. //
  205. // These parameters control the batching of MDLs queued for submission
  206. // to the network stack.
  207. //
  208. #define MAX_MDL_RUNS 8
  209. #define MAX_BYTES_BUFFERED (64 * 1024)
  210. #define MAX_BYTES_PER_READ (64 * 1024)
  211. //
  212. // Types of trackers
  213. //
  214. typedef enum _UL_TRACKER_TYPE
  215. {
  216. UlTrackerTypeSend,
  217. UlTrackerTypeBuildUriEntry,
  218. UlTrackerTypeMaximum
  219. } UL_TRACKER_TYPE, *PUL_TRACKER_TYPE;
  220. //
  221. // A MDL_RUN is a set of MDLs that came from the same source (either
  222. // a series of memory buffers, or data from a single file read) that
  223. // can be released all at once with the same mechanism.
  224. //
  225. typedef struct _MDL_RUN
  226. {
  227. PMDL pMdlTail;
  228. UL_FILE_BUFFER FileBuffer;
  229. } MDL_RUN, *PMDL_RUN;
  230. //
  231. // The UL_CHUNK_TRACKER is for iterating through the chunks in
  232. // a UL_INTERNAL_RESPONSE. It is used for sending responses
  233. // and generating cache entries.
  234. //
  235. // WARNING! All fields of this structure must be explicitly initialized.
  236. //
  237. typedef struct _UL_CHUNK_TRACKER
  238. {
  239. //
  240. // This MUST be the first field in the structure. This is the linkage
  241. // used by the lookaside package for storing entries in the lookaside
  242. // list.
  243. //
  244. SINGLE_LIST_ENTRY LookasideEntry;
  245. //
  246. // A signature.
  247. //
  248. ULONG Signature;
  249. //
  250. // Refcount on the tracker. We only use this refcount for the non-cache
  251. // case to sync various aynsc paths happening because of two outstanding
  252. // IRPs; Read and Send IRPs.
  253. //
  254. LONG RefCount;
  255. //
  256. // Flag to understand whether we have completed the send request on
  257. // this tracker or not. To synch the multiple completion paths.
  258. //
  259. LONG Terminated;
  260. //
  261. // Is this from a lookaside list? Used to determine how to free.
  262. //
  263. BOOLEAN IsFromLookaside;
  264. //
  265. // type of tracker
  266. //
  267. UL_TRACKER_TYPE Type;
  268. //
  269. // this connection keeps our reference count on the UL_CONNECTION
  270. //
  271. PUL_HTTP_CONNECTION pHttpConnection;
  272. //
  273. // the UL_CONNECTION
  274. //
  275. PUL_CONNECTION pConnection;
  276. //
  277. // Flags.
  278. //
  279. ULONG Flags;
  280. //
  281. // The original request.
  282. //
  283. PUL_INTERNAL_REQUEST pRequest;
  284. //
  285. // The actual response.
  286. //
  287. PUL_INTERNAL_RESPONSE pResponse;
  288. //
  289. // The current & last chunks in the response.
  290. //
  291. PUL_INTERNAL_DATA_CHUNK pCurrentChunk;
  292. PUL_INTERNAL_DATA_CHUNK pLastChunk;
  293. //
  294. // Completion routine & context.
  295. //
  296. PUL_COMPLETION_ROUTINE pCompletionRoutine;
  297. PVOID pCompletionContext;
  298. //
  299. // The variable header buffer
  300. //
  301. ULONG VariableHeaderLength;
  302. PUCHAR pVariableHeader;
  303. //
  304. // The precreated file read IRP.
  305. //
  306. PIRP pReadIrp;
  307. //
  308. // The precreated send IRP.
  309. //
  310. PIRP pSendIrp;
  311. //
  312. // The precreated IRP context for send.
  313. //
  314. UL_IRP_CONTEXT IrpContext;
  315. //
  316. // WARNING: RtlZeroMemory is only called for feilds below this line.
  317. // All fields above should be explicitly initialized.
  318. //
  319. //
  320. // A work item, used for queuing to a worker thread.
  321. //
  322. UL_WORK_ITEM WorkItem;
  323. //
  324. // Total number of bytes transferred for the entire
  325. // response. These are necessary to properly complete the IRP.
  326. //
  327. ULONGLONG BytesTransferred;
  328. //
  329. // Current file read offset and bytes remaining.
  330. //
  331. LARGE_INTEGER FileOffset;
  332. LARGE_INTEGER FileBytesRemaining;
  333. union {
  334. struct _SEND_TRACK_INFO {
  335. //
  336. // The head of the MDL chain buffered for this send.
  337. //
  338. PMDL pMdlHead;
  339. //
  340. // Pointer to the Next field of the last MDL on the chain.
  341. // This makes it very easy to append to the chain.
  342. //
  343. PMDL *pMdlLink;
  344. //
  345. // The number of bytes currently buffered in the MDL chain.
  346. //
  347. ULONG BytesBuffered;
  348. //
  349. // The number of active MDL runs.
  350. //
  351. ULONG MdlRunCount;
  352. //
  353. // The MDL runs.
  354. //
  355. MDL_RUN MdlRuns[MAX_MDL_RUNS];
  356. } SendInfo;
  357. struct _BUILD_TRACK_INFO {
  358. //
  359. // The cache entry
  360. //
  361. PUL_URI_CACHE_ENTRY pUriEntry;
  362. //
  363. // File buffer information for reading.
  364. //
  365. UL_FILE_BUFFER FileBuffer;
  366. //
  367. // Offset inside pUriEntry->pResponseMdl to copy the next buffer.
  368. //
  369. ULONG Offset;
  370. } BuildInfo;
  371. };
  372. IO_STATUS_BLOCK IoStatus;
  373. } UL_CHUNK_TRACKER, *PUL_CHUNK_TRACKER;
  374. #define IS_VALID_CHUNK_TRACKER( tracker ) \
  375. ( ((tracker)->Signature == UL_CHUNK_TRACKER_POOL_TAG) \
  376. && ((tracker)->Type < UlTrackerTypeMaximum) )
  377. #define IS_REQUEST_COMPLETE( tracker ) \
  378. ( (tracker)->pCurrentChunk == (tracker)->pLastChunk )
  379. #define IS_DISCONNECT_TIME( tracker ) \
  380. ( (((tracker)->Flags & HTTP_SEND_RESPONSE_FLAG_DISCONNECT) != 0) && \
  381. (((tracker)->Flags & HTTP_SEND_RESPONSE_FLAG_MORE_DATA) == 0) )
  382. #define CONNECTION_FROM_TRACKER( tracker ) \
  383. ( (tracker)->pConnection )
  384. //
  385. // This structure is for tracking an autonomous send with one full response
  386. //
  387. // WARNING! All fields of this structure must be explicitly initialized.
  388. //
  389. typedef struct _UL_FULL_TRACKER
  390. {
  391. //
  392. // This MUST be the first field in the structure. This is the linkage
  393. // used by the lookaside package for storing entries in the lookaside
  394. // list.
  395. //
  396. SINGLE_LIST_ENTRY LookasideEntry;
  397. //
  398. // A signature.
  399. //
  400. ULONG Signature;
  401. //
  402. // Is this from a lookaside list? Used to determine how to free.
  403. //
  404. BOOLEAN IsFromLookaside;
  405. //
  406. // Is this from the internal request? Won't try to free if set.
  407. //
  408. BOOLEAN IsFromRequest;
  409. //
  410. // A work item, used for queuing to a worker thread.
  411. //
  412. UL_WORK_ITEM WorkItem;
  413. //
  414. // The cache entry.
  415. //
  416. PUL_URI_CACHE_ENTRY pUriEntry;
  417. //
  418. // Preallocated buffer for the fixed headers, variable headers and entity
  419. // body to be copied in the cache-miss case, or for the variable headers
  420. // only in the cache-hit case.
  421. //
  422. ULONG AuxilaryBufferLength;
  423. PUCHAR pAuxiliaryBuffer;
  424. //
  425. // MDL for the variable headers in the cache-hit case or for both the
  426. // fixed headers and variable headers plus the copied entity body in
  427. // the cache-miss case.
  428. //
  429. union
  430. {
  431. PMDL pMdlVariableHeaders;
  432. PMDL pMdlAuxiliary;
  433. };
  434. //
  435. // MDL for the fixed headers in the cache-hit case or for the user
  436. // buffer in the cache-miss case.
  437. //
  438. union
  439. {
  440. PMDL pMdlFixedHeaders;
  441. PMDL pMdlUserBuffer;
  442. };
  443. //
  444. // MDL for the content in the cache-hit case.
  445. //
  446. PMDL pMdlContent;
  447. //
  448. // The original request that is saved for logging purpose.
  449. //
  450. PUL_INTERNAL_REQUEST pRequest;
  451. //
  452. // This connection keeps our reference count on the UL_CONNECTION.
  453. //
  454. PUL_HTTP_CONNECTION pHttpConnection;
  455. //
  456. // The log data captured if any.
  457. //
  458. PUL_LOG_DATA_BUFFER pLogData;
  459. //
  460. // Completion routine & context.
  461. //
  462. PUL_COMPLETION_ROUTINE pCompletionRoutine;
  463. PVOID pCompletionContext;
  464. //
  465. // Flags.
  466. //
  467. ULONG Flags;
  468. //
  469. // The precreated send IRP.
  470. //
  471. PIRP pSendIrp;
  472. //
  473. // The precreated IRP context for send.
  474. //
  475. UL_IRP_CONTEXT IrpContext;
  476. //
  477. // The orignal user send IRP if exists.
  478. //
  479. PIRP pUserIrp;
  480. //
  481. // SendBufferedBytes for this response.
  482. //
  483. LONG SendBufferedBytes;
  484. //
  485. // I/O status from the completion routine.
  486. //
  487. IO_STATUS_BLOCK IoStatus;
  488. } UL_FULL_TRACKER, *PUL_FULL_TRACKER;
  489. #define IS_VALID_FULL_TRACKER( tracker ) \
  490. ((tracker)->Signature == UL_FULL_TRACKER_POOL_TAG) \
  491. //
  492. // An inline function to initialize the full tracker.
  493. //
  494. __inline
  495. VOID
  496. FASTCALL
  497. UlInitializeFullTrackerPool(
  498. IN PUL_FULL_TRACKER pTracker,
  499. IN CCHAR SendIrpStackSize
  500. )
  501. {
  502. USHORT SendIrpSize;
  503. //
  504. // Set up the IRP.
  505. //
  506. SendIrpSize = IoSizeOfIrp(SendIrpStackSize);
  507. pTracker->pSendIrp =
  508. (PIRP)((PCHAR)pTracker +
  509. ALIGN_UP(sizeof(UL_FULL_TRACKER), PVOID));
  510. IoInitializeIrp(
  511. pTracker->pSendIrp,
  512. SendIrpSize,
  513. SendIrpStackSize
  514. );
  515. pTracker->pLogData = NULL;
  516. //
  517. // Set the Mdl's for the FixedHeaders/Variable pair and
  518. // the UserBuffer/AuxiliaryBuffer pair.
  519. //
  520. pTracker->pMdlFixedHeaders =
  521. (PMDL)((PCHAR)pTracker->pSendIrp + SendIrpSize);
  522. pTracker->pMdlVariableHeaders =
  523. (PMDL)((PCHAR)pTracker->pMdlFixedHeaders + g_UlFixedHeadersMdlLength);
  524. pTracker->pMdlContent =
  525. (PMDL)((PCHAR)pTracker->pMdlVariableHeaders + g_UlVariableHeadersMdlLength);
  526. //
  527. // Set up the auxiliary buffer pointer for the variable header plus
  528. // the fixed header and the entity body in the cache-miss case.
  529. //
  530. pTracker->pAuxiliaryBuffer =
  531. (PUCHAR)((PCHAR)pTracker->pMdlContent + g_UlContentMdlLength);
  532. //
  533. // Initialize the auxiliary MDL.
  534. //
  535. MmInitializeMdl(
  536. pTracker->pMdlAuxiliary,
  537. pTracker->pAuxiliaryBuffer,
  538. pTracker->AuxilaryBufferLength
  539. );
  540. MmBuildMdlForNonPagedPool( pTracker->pMdlAuxiliary );
  541. }
  542. NTSTATUS
  543. UlpProbeHttpResponse(
  544. IN PHTTP_RESPONSE pUserResponse,
  545. IN ULONG ChunkCount,
  546. IN PHTTP_DATA_CHUNK pDataChunks,
  547. IN ULONG Flags,
  548. IN PHTTP_LOG_FIELDS_DATA pLogData
  549. );
  550. NTSTATUS
  551. UlCaptureHttpResponse(
  552. IN PHTTP_RESPONSE pUserResponse OPTIONAL,
  553. IN PUL_INTERNAL_REQUEST pRequest,
  554. IN HTTP_VERSION Version,
  555. IN HTTP_VERB Verb,
  556. IN ULONG ChunkCount,
  557. IN PHTTP_DATA_CHUNK pDataChunks,
  558. IN UL_CAPTURE_FLAGS Flags,
  559. IN BOOLEAN CaptureCache,
  560. IN PHTTP_LOG_FIELDS_DATA pLogData OPTIONAL,
  561. OUT PUL_INTERNAL_RESPONSE *ppKernelResponse
  562. );
  563. NTSTATUS
  564. UlPrepareHttpResponse(
  565. IN HTTP_VERSION Version,
  566. IN PHTTP_RESPONSE pUserResponse,
  567. IN PUL_INTERNAL_RESPONSE pResponse
  568. );
  569. VOID
  570. UlCleanupHttpResponse(
  571. IN PUL_INTERNAL_RESPONSE pResponse
  572. );
  573. VOID
  574. UlReferenceHttpResponse(
  575. IN PUL_INTERNAL_RESPONSE pResponse
  576. REFERENCE_DEBUG_FORMAL_PARAMS
  577. );
  578. VOID
  579. UlDereferenceHttpResponse(
  580. IN PUL_INTERNAL_RESPONSE pResponse
  581. REFERENCE_DEBUG_FORMAL_PARAMS
  582. );
  583. #define UL_REFERENCE_INTERNAL_RESPONSE( presp ) \
  584. UlReferenceHttpResponse( \
  585. (presp) \
  586. REFERENCE_DEBUG_ACTUAL_PARAMS \
  587. )
  588. #define UL_DEREFERENCE_INTERNAL_RESPONSE( presp ) \
  589. UlDereferenceHttpResponse( \
  590. (presp) \
  591. REFERENCE_DEBUG_ACTUAL_PARAMS \
  592. )
  593. PMDL
  594. UlpAllocateLockedMdl(
  595. IN PVOID VirtualAddress,
  596. IN ULONG Length,
  597. IN LOCK_OPERATION Operation
  598. );
  599. VOID
  600. UlpFreeLockedMdl(
  601. PMDL pMdl
  602. );
  603. NTSTATUS
  604. UlpInitializeAndLockMdl(
  605. IN PMDL pMdl,
  606. IN PVOID VirtualAddress,
  607. IN ULONG Length,
  608. IN LOCK_OPERATION Operation
  609. );
  610. #ifdef __cplusplus
  611. }; // extern "C"
  612. #endif
  613. #endif // _SENDRESPONSE_H_