Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

631 lines
18 KiB

  1. /*++
  2. Copyright (c) 1998-2002 Microsoft Corporation
  3. Module Name:
  4. sendrequest.h
  5. Abstract:
  6. This module contains declarations for manipulating HTTP requests.
  7. Author:
  8. Rajesh Sundaram (rajeshsu)
  9. Revision History:
  10. --*/
  11. #ifndef _SENDREQUEST_H_
  12. #define _SENDREQUEST_H_
  13. //
  14. // Size of the lookaside for the send-request structure.
  15. //
  16. #define UC_REQUEST_LOOKASIDE_SIZE (sizeof(UC_HTTP_REQUEST)+1024)
  17. //
  18. // It takes 2 cycles per byte to RtlCopyMemory. It takes 1024 cycles to
  19. // ProbeLock and 1024 cycles to ProbeUnLock. So, as a rule, it is always
  20. // cheaper to copy if the BufferSize is < 2048.
  21. //
  22. #define UC_REQUEST_COPY_THRESHOLD (PAGE_SIZE/2)
  23. #define UC_REQUEST_HEADER_CHUNK_COUNT 1
  24. //
  25. // We allow the user to specify the chunk using a ULONG. So, the maximum chunk
  26. // size is FFFFFFFF <CRLF>. We add another CRLF for terminating the data.
  27. //
  28. #define UC_MAX_CHUNK_SIZE (10 + 2 * CRLF_SIZE)
  29. #define MULTIPART_SEPARATOR_SIZE 80
  30. //
  31. // Forwarders.
  32. //
  33. typedef struct _UC_HTTP_REQUEST *PUC_HTTP_REQUEST;
  34. typedef struct _UC_PROCESS_SERVER_INFORMATION *PUC_PROCESS_SERVER_INFORMATION;
  35. typedef struct _UC_CLIENT_CONNECTION *PUC_CLIENT_CONNECTION;
  36. //
  37. // This structure is used to store a parsed HTTP response.
  38. //
  39. #define UC_RESPONSE_EXTRA_BUFFER 1024
  40. #define UC_INSUFFICIENT_INDICATION_EXTRA_BUFFER 1024
  41. typedef struct _UC_RESPONSE_BUFFER
  42. {
  43. ULONG Signature;
  44. LIST_ENTRY Linkage;
  45. ULONG Flags;
  46. ULONG BytesWritten;
  47. ULONG BytesAllocated;
  48. HTTP_RESPONSE HttpResponse;
  49. } UC_RESPONSE_BUFFER, *PUC_RESPONSE_BUFFER;
  50. #define UC_RESPONSE_BUFFER_SIGNATURE MAKE_SIGNATURE('UcRB')
  51. #define IS_VALID_UC_RESPONSE_BUFFER(pBuffer) \
  52. HAS_VALID_SIGNATURE(pBuffer, UC_RESPONSE_BUFFER_SIGNATURE)
  53. //
  54. // Flags definition for UC_RESPONSE_BUFFER.Flags
  55. //
  56. #define UC_RESPONSE_BUFFER_FLAG_READY 0x00000001
  57. #define UC_RESPONSE_BUFFER_FLAG_NOT_MERGEABLE 0x00000002
  58. typedef enum _UC_RESPONSE_PARSER
  59. {
  60. UcParseStatusLineVersion,
  61. UcParseStatusLineStatusCode,
  62. UcParseStatusLineReasonPhrase,
  63. UcParseHeaders,
  64. UcParseEntityBody,
  65. UcParseTrailers,
  66. UcParseEntityBodyMultipartInit,
  67. UcParseEntityBodyMultipartHeaders,
  68. UcParseEntityBodyMultipartFinal,
  69. UcParseError,
  70. UcParseDone
  71. } UC_RESPONSE_PARSER_STATE, *PUC_RESPONSE_PARSER_STATE;
  72. typedef enum _UC_REQUEST_STATE
  73. {
  74. UcRequestStateCaptured, // has been captured
  75. UcRequestStateSent, // captured & sent.
  76. UcRequestStateSendCompleteNoData, // send has completed, but
  77. // haven't seen any response
  78. UcRequestStateSendCompletePartialData, // send has completed & we have
  79. // seen some response, but not all
  80. // of it.
  81. UcRequestStateNoSendCompletePartialData, // no send complete & we have seen
  82. // a portion of the response.
  83. UcRequestStateNoSendCompleteFullData, // no send complete & we have
  84. // seen all response.
  85. UcRequestStateResponseParsed, // fully parsed, send completed,
  86. // app has to post additional
  87. // receive buffers.
  88. UcRequestStateDone // app has seen all data.
  89. } UC_REQUEST_STATE, *PUC_REQUEST_STATE;
  90. //
  91. // Did we receive any response for this request?
  92. //
  93. #define UC_IS_RESPONSE_RECEIVED(pRequest) \
  94. (pRequest->RequestState == UcRequestStateSendCompletePartialData || \
  95. pRequest->RequestState == UcRequestStateNoSendCompletePartialData || \
  96. pRequest->RequestState == UcRequestStateNoSendCompleteFullData || \
  97. pRequest->RequestState == UcRequestStateResponseParsed)
  98. typedef union _UC_REQUEST_FLAGS
  99. {
  100. //
  101. // This field overlays all of the settable flags. This allows us to
  102. // update all flags in a thread-safe manner using the
  103. // UlInterlockedCompareExchange() API.
  104. //
  105. LONG Value;
  106. struct
  107. {
  108. ULONG CleanPended:1; // 00000001
  109. ULONG RequestChunked:1; // 00000002
  110. ULONG LastEntitySeen:1; // 00000004
  111. ULONG ContentLengthSpecified:1; // 00000008
  112. ULONG ReceiveBufferSpecified:1; // 00000010
  113. ULONG RequestBuffered:1; // 00000020
  114. ULONG CompleteIrpEarly:1; // 00000040
  115. ULONG ContentLengthLast:1; // 00000080
  116. ULONG PipeliningAllowed:1; // 00000100
  117. ULONG CancelSet:1; // 00000200
  118. ULONG NoResponseEntityBodies:1; // 00000400
  119. ULONG ProxySslConnect:1; // 00000800
  120. ULONG Cancelled:1; // 00001000
  121. ULONG NoRequestEntityBodies:1; // 00002000
  122. ULONG UsePreAuth:1; // 00004000
  123. ULONG UseProxyPreAuth:1; // 00008000
  124. };
  125. } UC_REQUEST_FLAGS;
  126. #define UC_MAKE_REQUEST_FLAG_ROUTINE(name) \
  127. __inline LONG UcMakeRequest##name##Flag() \
  128. { \
  129. UC_REQUEST_FLAGS flags = { 0 }; \
  130. flags.name = 1; \
  131. return flags.Value; \
  132. }
  133. UC_MAKE_REQUEST_FLAG_ROUTINE( RequestChunked );
  134. UC_MAKE_REQUEST_FLAG_ROUTINE( LastEntitySeen );
  135. UC_MAKE_REQUEST_FLAG_ROUTINE( ContentLengthSpecified );
  136. UC_MAKE_REQUEST_FLAG_ROUTINE( ContentLengthLast );
  137. UC_MAKE_REQUEST_FLAG_ROUTINE( CancelSet );
  138. UC_MAKE_REQUEST_FLAG_ROUTINE( Cancelled );
  139. UC_MAKE_REQUEST_FLAG_ROUTINE( CleanPended );
  140. #define UC_REQUEST_RECEIVE_READY (1L)
  141. #define UC_REQUEST_RECEIVE_BUSY (2L)
  142. #define UC_REQUEST_RECEIVE_CANCELLED (3L)
  143. typedef struct _UC_HTTP_REQUEST
  144. {
  145. ULONG Signature;
  146. LIST_ENTRY Linkage;
  147. LONG RefCount;
  148. ULONGLONG RequestContentLengthRemaining;
  149. NTSTATUS RequestStatus;
  150. UC_REQUEST_FLAGS RequestFlags;
  151. HTTP_REQUEST_ID RequestId;
  152. UL_WORK_ITEM WorkItem;
  153. //
  154. // We could be piggybacking on the applications IRP.
  155. // if this is the case, we need to restore some
  156. // parameters.
  157. //
  158. KPROCESSOR_MODE AppRequestorMode;
  159. UCHAR Pad[3];
  160. PMDL AppMdl;
  161. PIRP RequestIRP;
  162. PIO_STACK_LOCATION RequestIRPSp;
  163. ULONG RequestIRPBytesWritten;
  164. PFILE_OBJECT pFileObject;
  165. PUC_CLIENT_CONNECTION pConnection;
  166. ULONG ConnectionIndex;
  167. //
  168. // All the MDL information.
  169. //
  170. PMDL pMdlHead;
  171. PMDL *pMdlLink; // Pointer to the head of the MDL chain.
  172. // used to easily chain MDLs.
  173. ULONG BytesBuffered; // Total # of bytes buffered in
  174. // the MDL chains.
  175. //
  176. // For holding the parsed respose.
  177. //
  178. UC_RESPONSE_PARSER_STATE ParseState;
  179. UC_REQUEST_STATE RequestState;
  180. //
  181. // The following fields hold data pertaining to the current buffer that
  182. // the parser has to write its response to. The current buffer could
  183. // either be the buffer passed by the application, or it could point to an
  184. // internally allocated buffer.
  185. //
  186. // All internally allocated buffers are stored in pBufferList.
  187. //
  188. PHTTP_RESPONSE pInternalResponse;
  189. struct {
  190. ULONG BytesAllocated;
  191. ULONG BytesAvailable;
  192. PUCHAR pOutBufferHead; // Pointer to the head of output
  193. // buffer
  194. PUCHAR pOutBufferTail; // Pointer to the tail of
  195. // output buffer
  196. PHTTP_RESPONSE pResponse; // pointer to the response
  197. // structure of current buffer
  198. PUC_RESPONSE_BUFFER pCurrentBuffer; // A pointer to the current
  199. // buffer.
  200. } CurrentBuffer;
  201. LIST_ENTRY pBufferList; // This holds a list of chained
  202. // buffers.
  203. LIST_ENTRY ReceiveResponseIrpList;
  204. BOOLEAN ResponseMultipartByteranges;
  205. BOOLEAN ResponseConnectionClose;
  206. BOOLEAN RequestConnectionClose;
  207. BOOLEAN ResponseVersion11;
  208. BOOLEAN ResponseEncodingChunked;
  209. BOOLEAN ResponseContentLengthSpecified;
  210. BOOLEAN DontFreeMdls;
  211. BOOLEAN Renegotiate;
  212. ULONGLONG ResponseContentLength;
  213. ULONG ParsedFirstChunk;
  214. SIZE_T RequestSize;
  215. LIST_ENTRY PendingEntityList;
  216. LIST_ENTRY SentEntityList;
  217. ULONG MaxHeaderLength;
  218. ULONG HeaderLength;
  219. PUCHAR pHeaders;
  220. FAST_MUTEX Mutex;
  221. PUC_HTTP_AUTH pAuthInfo;
  222. PUC_HTTP_AUTH pProxyAuthInfo;
  223. PCHAR pMultipartStringSeparator;
  224. CHAR MultipartStringSeparatorBuffer[MULTIPART_SEPARATOR_SIZE];
  225. ULONG MultipartStringSeparatorLength;
  226. ULONG MultipartRangeRemaining;
  227. ULONG ResponseStatusCode;
  228. PUC_PROCESS_SERVER_INFORMATION pServerInfo;
  229. PSTR pUri;
  230. USHORT UriLength;
  231. LONG ReceiveBusy;
  232. } UC_HTTP_REQUEST, *PUC_HTTP_REQUEST;
  233. //
  234. // Http request can go out on any available connection.
  235. //
  236. #define HTTP_REQUEST_ON_CONNECTION_ANY (~(0UL))
  237. typedef struct _UC_HTTP_RECEIVE_RESPONSE
  238. {
  239. LIST_ENTRY Linkage;
  240. PIRP pIrp;
  241. BOOLEAN CancelSet;
  242. PUC_HTTP_REQUEST pRequest;
  243. LIST_ENTRY ResponseBufferList;
  244. } UC_HTTP_RECEIVE_RESPONSE, *PUC_HTTP_RECEIVE_RESPONSE;
  245. typedef struct _UC_HTTP_SEND_ENTITY_BODY
  246. {
  247. ULONG Signature;
  248. LIST_ENTRY Linkage;
  249. PIRP pIrp;
  250. BOOLEAN CancelSet;
  251. BOOLEAN Last;
  252. PUC_HTTP_REQUEST pRequest;
  253. PMDL pMdlHead;
  254. PMDL *pMdlLink;
  255. ULONG BytesBuffered;
  256. KPROCESSOR_MODE AppRequestorMode;
  257. UCHAR Pad[3];
  258. PMDL AppMdl;
  259. SIZE_T BytesAllocated;
  260. } UC_HTTP_SEND_ENTITY_BODY, *PUC_HTTP_SEND_ENTITY_BODY;
  261. #define UC_REQUEST_SIGNATURE MAKE_SIGNATURE('HREQ')
  262. #define UC_REQUEST_SIGNATURE_X MAKE_FREE_SIGNATURE(UC_REQUEST_SIGNATURE)
  263. #define UC_ENTITY_SIGNATURE MAKE_SIGNATURE('HENT')
  264. #define UC_ENTITY_SIGNATURE_X MAKE_FREE_SIGNATURE(UC_REQUEST_SIGNATURE)
  265. #define UC_IS_VALID_HTTP_REQUEST(pRequest) \
  266. HAS_VALID_SIGNATURE(pRequest, UC_REQUEST_SIGNATURE)
  267. #define UC_REFERENCE_REQUEST(s) \
  268. UcReferenceRequest( \
  269. (s) \
  270. REFERENCE_DEBUG_ACTUAL_PARAMS \
  271. )
  272. #define UC_DEREFERENCE_REQUEST(s) \
  273. UcDereferenceRequest( \
  274. (s) \
  275. REFERENCE_DEBUG_ACTUAL_PARAMS \
  276. )
  277. NTSTATUS
  278. UcCaptureHttpRequest(IN PUC_PROCESS_SERVER_INFORMATION pServInfo,
  279. IN PHTTP_SEND_REQUEST_INPUT_INFO pHttpRequest,
  280. IN PIRP Irp,
  281. IN PIO_STACK_LOCATION IrpSp,
  282. OUT PUC_HTTP_REQUEST *ppInternalRequest,
  283. IN PULONG pBytesTaken);
  284. VOID
  285. UcpProbeAndCopyHttpRequest(
  286. IN PHTTP_REQUEST pHttpRequest,
  287. IN PHTTP_REQUEST pLocalHttpRequest,
  288. IN KPROCESSOR_MODE RequestorMode
  289. );
  290. VOID
  291. UcpRetrieveContentLength(
  292. IN PHTTP_REQUEST pHttpRequest,
  293. OUT PBOOLEAN pbContentLengthSpecified,
  294. OUT PULONGLONG pContentLength
  295. );
  296. VOID
  297. UcpRequestInitialize(
  298. IN PUC_HTTP_REQUEST pRequest,
  299. IN SIZE_T RequestLength,
  300. IN ULONGLONG RemainingContentLength,
  301. IN PUC_HTTP_AUTH pAuth,
  302. IN PUC_HTTP_AUTH pProxyAuth,
  303. IN PUC_CLIENT_CONNECTION pConnection,
  304. IN PIRP Irp,
  305. IN PIO_STACK_LOCATION pIrpSp,
  306. IN PUC_PROCESS_SERVER_INFORMATION pServerInfo
  307. );
  308. VOID
  309. UcpRequestCommonInitialize(
  310. IN PUC_HTTP_REQUEST pRequest,
  311. IN ULONG OutLength,
  312. IN PUCHAR pBuffer
  313. );
  314. VOID
  315. UcpFixAppBufferPointers(
  316. PUC_HTTP_REQUEST pRequest,
  317. PIRP pIrp
  318. );
  319. VOID
  320. UcpProbeConfigList(
  321. IN PHTTP_REQUEST_CONFIG pRequestConfig,
  322. IN USHORT RequestConfigCount,
  323. IN KPROCESSOR_MODE RequestorMode,
  324. IN PUC_PROCESS_SERVER_INFORMATION pServInfo,
  325. IN PUC_HTTP_AUTH *ppIAuth,
  326. IN PUC_HTTP_AUTH *ppIProxyAuth,
  327. IN PULONG pConnectionIndex
  328. );
  329. VOID
  330. UcFreeSendMdls(
  331. IN PMDL pMdl
  332. );
  333. VOID
  334. UcReferenceRequest(
  335. IN PVOID pObject
  336. REFERENCE_DEBUG_FORMAL_PARAMS
  337. );
  338. VOID
  339. UcDereferenceRequest(
  340. IN PVOID pObject
  341. REFERENCE_DEBUG_FORMAL_PARAMS
  342. );
  343. PIRP
  344. UcPrepareRequestIrp(
  345. IN PUC_HTTP_REQUEST pRequest,
  346. IN NTSTATUS Status
  347. );
  348. NTSTATUS
  349. UcCompleteParsedRequest(
  350. IN PUC_HTTP_REQUEST pRequest,
  351. IN NTSTATUS Status,
  352. IN BOOLEAN NextRequest,
  353. IN KIRQL OldIrql
  354. );
  355. BOOLEAN
  356. UcSetRequestCancelRoutine(
  357. PUC_HTTP_REQUEST pRequest,
  358. PDRIVER_CANCEL pCancelRoutine
  359. );
  360. BOOLEAN
  361. UcRemoveRequestCancelRoutine(
  362. PUC_HTTP_REQUEST pRequest
  363. );
  364. BOOLEAN
  365. UcSetEntityCancelRoutine(
  366. PUC_HTTP_SEND_ENTITY_BODY pEntity,
  367. PDRIVER_CANCEL pCancelRoutine
  368. );
  369. BOOLEAN
  370. UcRemoveEntityCancelRoutine(
  371. PUC_HTTP_SEND_ENTITY_BODY pEntity
  372. );
  373. BOOLEAN
  374. UcSetRecvResponseCancelRoutine(
  375. PUC_HTTP_RECEIVE_RESPONSE pResponse,
  376. PDRIVER_CANCEL pCancelRoutine
  377. );
  378. BOOLEAN
  379. UcRemoveRcvRespCancelRoutine(
  380. PUC_HTTP_RECEIVE_RESPONSE pResponse
  381. );
  382. VOID
  383. UcpFreeRequest(
  384. IN PUL_WORK_ITEM pWorkItem
  385. );
  386. NTSTATUS
  387. UcCopyResponseToIrp(
  388. PIRP pIrp,
  389. PLIST_ENTRY pResponseBufferList,
  390. PBOOLEAN bDone,
  391. PULONG pBytesTaken
  392. );
  393. NTSTATUS
  394. UcReceiveHttpResponse(
  395. IN PUC_HTTP_REQUEST pRequest,
  396. IN PIRP pIrp,
  397. IN PULONG pBytesTaken
  398. );
  399. VOID
  400. UcpCancelReceiveResponse(
  401. PDEVICE_OBJECT pDeviceObject,
  402. PIRP Irp
  403. );
  404. VOID
  405. UcpCancelSendEntity(
  406. PDEVICE_OBJECT pDeviceObject,
  407. PIRP Irp
  408. );
  409. VOID
  410. UcpComputeEntityBodyLength(
  411. USHORT EntityChunkCount,
  412. PHTTP_DATA_CHUNK pEntityChunks,
  413. BOOLEAN bContentLengthSpecified,
  414. BOOLEAN bServer11,
  415. PULONGLONG UncopiedLength,
  416. PULONGLONG CopiedLength
  417. );
  418. NTSTATUS
  419. UcCaptureEntityBody(
  420. PHTTP_SEND_REQUEST_ENTITY_BODY_INFO pSendInfo,
  421. PIRP Irp,
  422. PUC_HTTP_REQUEST pRequest,
  423. PUC_HTTP_SEND_ENTITY_BODY *ppKeEntity,
  424. BOOLEAN bLast
  425. );
  426. NTSTATUS
  427. UcpBuildEntityMdls(
  428. USHORT ChunkCount,
  429. PHTTP_DATA_CHUNK pHttpEntityBody,
  430. BOOLEAN bServer11,
  431. BOOLEAN bChunked,
  432. BOOLEAN bLast,
  433. PSTR pBuffer,
  434. PMDL **pMdlLink,
  435. PULONG BytesBuffered
  436. );
  437. NTSTATUS
  438. UcInitializeHttpRequests(
  439. VOID
  440. );
  441. VOID
  442. UcTerminateHttpRequests(
  443. VOID
  444. );
  445. VOID
  446. UcAllocateAndChainHeaderMdl(
  447. IN PUC_HTTP_REQUEST pRequest
  448. );
  449. VOID
  450. UcpAllocateAndChainEntityMdl(
  451. IN PVOID pMdlBuffer,
  452. IN ULONG MdlLength,
  453. IN PMDL **pMdlLink,
  454. IN PULONG BytesBuffered
  455. );
  456. PUC_HTTP_REQUEST
  457. UcBuildConnectVerbRequest(
  458. IN PUC_CLIENT_CONNECTION pConnection,
  459. IN PUC_HTTP_REQUEST pHeadRequest
  460. );
  461. VOID
  462. UcFailRequest(
  463. IN PUC_HTTP_REQUEST pRequest,
  464. IN NTSTATUS Status,
  465. IN KIRQL OldIrql
  466. );
  467. VOID
  468. UcReIssueRequestWorker(
  469. IN PUL_WORK_ITEM pWorkItem
  470. );
  471. VOID
  472. UcpProbeAndCopyEntityChunks(
  473. IN KPROCESSOR_MODE RequestorMode,
  474. IN PHTTP_DATA_CHUNK pEntityChunks,
  475. IN ULONG EntityChunkCount,
  476. IN PHTTP_DATA_CHUNK pLocalEntityChunksArray,
  477. OUT PHTTP_DATA_CHUNK *ppLocalEntityChunks
  478. );
  479. #define IS_MDL_LOCKED(pmdl) (((pmdl)->MdlFlags & MDL_PAGES_LOCKED) != 0)
  480. NTSTATUS
  481. UcFindBuffersForReceiveResponseIrp(
  482. IN PUC_HTTP_REQUEST pRequest,
  483. IN ULONG OutBufferLen,
  484. IN BOOLEAN bForceComplete,
  485. OUT PLIST_ENTRY pResponseBufferList,
  486. OUT PULONG pTotalBytes
  487. );
  488. VOID
  489. UcpPreAuthWorker(
  490. IN PUL_WORK_ITEM pWorkItem
  491. );
  492. __inline
  493. BOOLEAN
  494. UcpCheckForPreAuth(
  495. IN PUC_HTTP_REQUEST pRequest
  496. );
  497. __inline
  498. BOOLEAN
  499. UcpCheckForProxyPreAuth(
  500. IN PUC_HTTP_REQUEST pRequest
  501. );
  502. #endif