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.

452 lines
11 KiB

  1. /*++
  2. Copyright (c) 2000-2001 Microsoft Corporation
  3. Module Name:
  4. fastio.h
  5. Abstract:
  6. This module contains declarations related to fast I/O.
  7. Author:
  8. Chun Ye (chunye) 09-Dec-2000
  9. Revision History:
  10. --*/
  11. #ifndef _FASTIO_H_
  12. #define _FASTIO_H_
  13. #ifdef __cplusplus
  14. extern "C" {
  15. #endif
  16. //
  17. // Some useful macroes.
  18. //
  19. #define IS_LENGTH_SPECIFIED( pKnownHeaders ) \
  20. (pKnownHeaders[HttpHeaderContentLength].RawValueLength > 0)
  21. #define IS_CHUNK_SPECIFIED( pKnownHeaders ) \
  22. (pKnownHeaders[HttpHeaderTransferEncoding].RawValueLength > 0 && \
  23. 0 == _strnicmp( \
  24. pKnownHeaders[HttpHeaderTransferEncoding].pRawValue, \
  25. "chunked", \
  26. strlen("chunked") \
  27. )) \
  28. //
  29. // Inline functions to allocate/free a fast tracker.
  30. //
  31. __inline
  32. PUL_FULL_TRACKER
  33. FASTCALL
  34. UlpAllocateFastTracker(
  35. IN ULONG FixedHeaderLength,
  36. IN CCHAR SendIrpStackSize
  37. )
  38. {
  39. PUL_FULL_TRACKER pTracker;
  40. ULONG SpaceLength;
  41. ULONG MaxFixedHeaderSize;
  42. USHORT MaxSendIrpSize;
  43. CCHAR MaxSendIrpStackSize;
  44. //
  45. // Sanity check.
  46. //
  47. PAGED_CODE();
  48. if (FixedHeaderLength > g_UlMaxFixedHeaderSize ||
  49. SendIrpStackSize > DEFAULT_MAX_IRP_STACK_SIZE)
  50. {
  51. MaxFixedHeaderSize = MAX(FixedHeaderLength, g_UlMaxFixedHeaderSize);
  52. MaxSendIrpStackSize = MAX(SendIrpStackSize, DEFAULT_MAX_IRP_STACK_SIZE);
  53. MaxSendIrpSize = (USHORT)ALIGN_UP(IoSizeOfIrp(MaxSendIrpStackSize), PVOID);
  54. SpaceLength =
  55. ALIGN_UP(sizeof(UL_FULL_TRACKER), PVOID) +
  56. MaxSendIrpSize +
  57. MaxFixedHeaderSize +
  58. g_UlMaxVariableHeaderSize +
  59. g_UlMaxCopyThreshold +
  60. g_UlFixedHeadersMdlLength +
  61. g_UlVariableHeadersMdlLength +
  62. g_UlContentMdlLength;
  63. pTracker = (PUL_FULL_TRACKER)UL_ALLOCATE_POOL(
  64. NonPagedPool,
  65. SpaceLength,
  66. UL_FULL_TRACKER_POOL_TAG
  67. );
  68. if (pTracker)
  69. {
  70. pTracker->Signature = UL_FULL_TRACKER_POOL_TAG;
  71. pTracker->IrpContext.Signature = UL_IRP_CONTEXT_SIGNATURE;
  72. pTracker->IsFromLookaside = FALSE;
  73. pTracker->IsFromRequest = FALSE;
  74. pTracker->AuxilaryBufferLength =
  75. MaxFixedHeaderSize +
  76. g_UlMaxVariableHeaderSize +
  77. g_UlMaxCopyThreshold;
  78. UlInitializeFullTrackerPool( pTracker, MaxSendIrpStackSize );
  79. }
  80. }
  81. else
  82. {
  83. pTracker = UlPplAllocateFullTracker();
  84. if (pTracker)
  85. {
  86. ASSERT(pTracker->Signature == MAKE_FREE_TAG(UL_FULL_TRACKER_POOL_TAG));
  87. pTracker->Signature = UL_FULL_TRACKER_POOL_TAG;
  88. pTracker->pLogData = NULL;
  89. // BUGBUG: I know we're trying to squeeze every last cycle
  90. // out of the fast path, but can we really get away with
  91. // this little initialization?
  92. }
  93. }
  94. return pTracker;
  95. } // UlpAllocateFastTracker
  96. __inline
  97. VOID
  98. FASTCALL
  99. UlpFreeFastTracker(
  100. IN PUL_FULL_TRACKER pTracker
  101. )
  102. {
  103. //
  104. // Sanity check.
  105. //
  106. PAGED_CODE();
  107. ASSERT( IS_VALID_FULL_TRACKER( pTracker ) );
  108. if (pTracker->pLogData)
  109. {
  110. UlDestroyLogDataBuffer( pTracker->pLogData );
  111. }
  112. if (pTracker->IsFromRequest == FALSE)
  113. {
  114. if (pTracker->IsFromLookaside)
  115. {
  116. pTracker->Signature = MAKE_FREE_TAG(UL_FULL_TRACKER_POOL_TAG);
  117. UlPplFreeFullTracker( pTracker );
  118. }
  119. else
  120. {
  121. UL_FREE_POOL_WITH_SIG( pTracker, UL_FULL_TRACKER_POOL_TAG );
  122. }
  123. }
  124. } // UlpFreeFastTracker
  125. //
  126. // Dispatch routines for fast I/O.
  127. //
  128. extern FAST_IO_DISPATCH UlFastIoDispatch;
  129. //
  130. // Fast I/O routines.
  131. //
  132. BOOLEAN
  133. UlFastIoDeviceControl (
  134. IN PFILE_OBJECT pFileObject,
  135. IN BOOLEAN Wait,
  136. IN PVOID pInputBuffer OPTIONAL,
  137. IN ULONG InputBufferLength,
  138. OUT PVOID pOutputBuffer OPTIONAL,
  139. IN ULONG OutputBufferLength,
  140. IN ULONG IoControlCode,
  141. OUT PIO_STATUS_BLOCK pIoStatus,
  142. IN PDEVICE_OBJECT pDeviceObject
  143. );
  144. BOOLEAN
  145. UlSendHttpResponseFastIo(
  146. IN PFILE_OBJECT pFileObject,
  147. IN BOOLEAN Wait,
  148. IN PVOID pInputBuffer OPTIONAL,
  149. IN ULONG InputBufferLength,
  150. OUT PVOID pOutputBuffer OPTIONAL,
  151. IN ULONG OutputBufferLength,
  152. OUT PIO_STATUS_BLOCK pIoStatus,
  153. IN PDEVICE_OBJECT pDeviceObject,
  154. IN BOOLEAN RawResponse
  155. );
  156. BOOLEAN
  157. UlReceiveHttpRequestFastIo(
  158. IN PFILE_OBJECT pFileObject,
  159. IN BOOLEAN Wait,
  160. IN PVOID pInputBuffer OPTIONAL,
  161. IN ULONG InputBufferLength,
  162. OUT PVOID pOutputBuffer OPTIONAL,
  163. IN ULONG OutputBufferLength,
  164. OUT PIO_STATUS_BLOCK pIoStatus,
  165. IN PDEVICE_OBJECT pDeviceObject
  166. );
  167. //
  168. // Private prototypes.
  169. //
  170. NTSTATUS
  171. UlpFastSendHttpResponse(
  172. IN PHTTP_RESPONSE pUserResponse OPTIONAL,
  173. IN PHTTP_LOG_FIELDS_DATA pLogData OPTIONAL,
  174. IN PHTTP_DATA_CHUNK pDataChunk,
  175. IN ULONG ChunkCount,
  176. IN ULONG Flags,
  177. IN PUL_INTERNAL_REQUEST pRequest,
  178. IN PIRP pUserIrp OPTIONAL,
  179. OUT PULONG BytesSent
  180. );
  181. VOID
  182. UlpRestartFastSendHttpResponse(
  183. IN PVOID pCompletionContext,
  184. IN NTSTATUS Status,
  185. IN ULONG_PTR Information
  186. );
  187. VOID
  188. UlpFastSendCompleteWorker(
  189. IN PUL_WORK_ITEM pWorkItem
  190. );
  191. NTSTATUS
  192. UlpFastReceiveHttpRequest(
  193. IN HTTP_REQUEST_ID RequestId,
  194. IN PUL_APP_POOL_PROCESS pProcess,
  195. IN PVOID pOutputBuffer,
  196. IN ULONG OutputBufferLength,
  197. OUT PULONG pBytesRead
  198. );
  199. NTSTATUS
  200. UlpFastCopyHttpRequest(
  201. IN PUL_INTERNAL_REQUEST pRequest,
  202. IN PVOID pOutputBuffer,
  203. IN ULONG OutputBufferLength,
  204. OUT PULONG pBytesRead
  205. );
  206. //
  207. // An inline function to generate the content-length string.
  208. //
  209. __inline
  210. ULONG
  211. FASTCALL
  212. UlpFastGenerateContentLength(
  213. IN PCHAR LengthString,
  214. IN ULONG Length
  215. )
  216. {
  217. ASSERT( ALIGN_UP_POINTER(LengthString, ULONG) == (PVOID)LengthString );
  218. ASSERT( Length < 100000 );
  219. if (Length >= 10000)
  220. {
  221. *((PULONG)LengthString) = *((PULONG)"0000");
  222. LengthString[0] += (CHAR)((Length / 10000) % 10);
  223. LengthString[1] += (CHAR)((Length / 1000) % 10);
  224. LengthString[2] += (CHAR)((Length / 100) % 10);
  225. LengthString[3] += (CHAR)((Length / 10) % 10);
  226. LengthString[4] = (CHAR)('0' + (Length / 1) % 10);
  227. LengthString[5] = ANSI_NULL;
  228. return 5;
  229. }
  230. else
  231. if (Length >= 1000)
  232. {
  233. *((PULONG)LengthString) = *((PULONG)"0000");
  234. LengthString[0] += (CHAR)((Length / 1000) % 10);
  235. LengthString[1] += (CHAR)((Length / 100) % 10);
  236. LengthString[2] += (CHAR)((Length / 10) % 10);
  237. LengthString[3] += (CHAR)((Length / 1) % 10);
  238. LengthString[4] = ANSI_NULL;
  239. return 4;
  240. }
  241. else
  242. if (Length >= 100)
  243. {
  244. *((PULONG)LengthString) = *((PULONG)"0000");
  245. LengthString[0] += (CHAR)((Length / 100) % 10);
  246. LengthString[1] += (CHAR)((Length / 10) % 10);
  247. LengthString[2] += (CHAR)((Length / 1) % 10);
  248. LengthString[3] = ANSI_NULL;
  249. return 3;
  250. }
  251. else
  252. if (Length >= 10)
  253. {
  254. *((PUSHORT)LengthString) = *((PUSHORT)"00");
  255. LengthString[0] += (CHAR)((Length / 10) % 10);
  256. LengthString[1] += (CHAR)((Length / 1) % 10);
  257. LengthString[2] = ANSI_NULL;
  258. return 2;
  259. }
  260. else
  261. {
  262. LengthString[0] = (CHAR)('0' + (Length / 1) % 10);
  263. LengthString[1] = ANSI_NULL;
  264. return 1;
  265. }
  266. } // UlpFastGenerateContentLength
  267. //
  268. // An inline function to ProbeForRead the header portions of the HTTP_RESPONSE.
  269. //
  270. #define UL_MAX_HTTP_STATUS_CODE 999
  271. __inline
  272. NTSTATUS
  273. FASTCALL
  274. UlProbeHttpHeaders(
  275. IN PHTTP_RESPONSE pUserResponse
  276. )
  277. {
  278. NTSTATUS Status;
  279. PHTTP_UNKNOWN_HEADER pUnknownHeaders;
  280. USHORT Length;
  281. LONG i;
  282. Status = STATUS_SUCCESS;
  283. if (pUserResponse == NULL)
  284. {
  285. return Status;
  286. }
  287. __try
  288. {
  289. //
  290. // Check flags and status code.
  291. //
  292. if ((pUserResponse->Flags & ~HTTP_RESPONSE_FLAG_VALID) ||
  293. (pUserResponse->StatusCode > UL_MAX_HTTP_STATUS_CODE))
  294. {
  295. ExRaiseStatus( STATUS_INVALID_PARAMETER );
  296. }
  297. //
  298. // Check the response structure.
  299. //
  300. ProbeTestForRead(
  301. pUserResponse,
  302. sizeof(HTTP_RESPONSE),
  303. sizeof(USHORT)
  304. );
  305. //
  306. // Check the reason string.
  307. //
  308. ProbeTestForRead(
  309. pUserResponse->pReason,
  310. pUserResponse->ReasonLength,
  311. sizeof(CHAR)
  312. );
  313. //
  314. // Loop through the known headers.
  315. //
  316. for (i = 0; i < HttpHeaderResponseMaximum; i++)
  317. {
  318. Length = pUserResponse->Headers.pKnownHeaders[i].RawValueLength;
  319. if (Length > 0)
  320. {
  321. ProbeTestForRead(
  322. pUserResponse->Headers.pKnownHeaders[i].pRawValue,
  323. Length,
  324. sizeof(CHAR)
  325. );
  326. }
  327. }
  328. //
  329. // And the unknown headers (this might throw an exception).
  330. //
  331. pUnknownHeaders = pUserResponse->Headers.pUnknownHeaders;
  332. if (pUnknownHeaders != NULL)
  333. {
  334. ProbeTestForRead(
  335. pUnknownHeaders,
  336. sizeof(HTTP_UNKNOWN_HEADER) * pUserResponse->Headers.UnknownHeaderCount,
  337. sizeof(ULONG)
  338. );
  339. for (i = 0; i < (LONG)(pUserResponse->Headers.UnknownHeaderCount); i++)
  340. {
  341. if (pUnknownHeaders[i].NameLength > 0)
  342. {
  343. ProbeTestForRead(
  344. pUnknownHeaders[i].pName,
  345. pUnknownHeaders[i].NameLength,
  346. sizeof(CHAR)
  347. );
  348. ProbeTestForRead(
  349. pUnknownHeaders[i].pRawValue,
  350. pUnknownHeaders[i].RawValueLength,
  351. sizeof(CHAR)
  352. );
  353. }
  354. }
  355. }
  356. UlTrace(IOCTL,
  357. ("UlProbeHttpHeaders validated the headers: %x\n", Status));
  358. }
  359. __except( UL_EXCEPTION_FILTER() )
  360. {
  361. Status = UL_CONVERT_EXCEPTION_CODE(GetExceptionCode());
  362. UlTrace(IOCTL,
  363. ("UlProbeHttpHeaders caught an exception: %x\n", Status));
  364. }
  365. return Status;
  366. } // UlProbeHttpHeaders
  367. #ifdef __cplusplus
  368. }; // extern "C"
  369. #endif
  370. #endif // _FASTIO_H_