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.

404 lines
8.6 KiB

  1. Requirements for abstracting the parsing code out of UL:
  2. Functions exported by the parser:
  3. InitializeParser()
  4. ParseHttp()
  5. ParseChunkLength()
  6. Types used by the interface:
  7. HTTP_REQUEST
  8. * UL_HTTP_VERB Verb
  9. * PUCHAR pRawVerb
  10. * ULONG RawVerbLength
  11. * ULONG TotalRequestSize
  12. * struct {} RawUrl
  13. * ULONG PortInHost
  14. * LIST_ENTRY UnknownHeaderList
  15. * ULONG UnknownHeaderCount
  16. * ULONGLONG BytesLeftInChunk
  17. * ULONG LastChunk
  18. * PARSE_STATE ParseState
  19. * UL_HTTP_VERSION Version
  20. * HTTP_HEADER Headers[]
  21. * ULONGLONG ContentLength
  22. * ULONG Chunked
  23. * struct {} CookedUrl
  24. PHTTP_CONNECTION pHttpConn -- For UlIpAddressFromConnection
  25. typedef struct _HTTP_PARSE_INFO
  26. {
  27. //
  28. // Structure signature.
  29. //
  30. ULONG Signature;
  31. //
  32. // Current state of our parsing effort.
  33. //
  34. PARSE_STATE ParseState;
  35. //
  36. // Verb of this request.
  37. //
  38. UL_HTTP_VERB Verb;
  39. //
  40. // Request version.
  41. //
  42. UL_HTTP_VERSION Version;
  43. //
  44. // Array of headers we do know about.
  45. //
  46. HTTP_HEADER Headers[UlHeaderMaximum];
  47. //
  48. // Pointer to the raw verb, valid only if Verb == UlHttpVerbUnknown.
  49. //
  50. PUCHAR pRawVerb;
  51. //
  52. // Length of the raw verb.
  53. //
  54. ULONG RawVerbLength;
  55. //
  56. // Total bytes needed for this request, including string terminators.
  57. //
  58. ULONG TotalRequestSize;
  59. //
  60. // List of headers we don't know about.
  61. //
  62. LIST_ENTRY UnknownHeaderList;
  63. //
  64. // The number of "unknown" headers we have.
  65. //
  66. ULONG UnknownHeaderCount;
  67. //
  68. // The content length, if any.
  69. //
  70. ULONGLONG ContentLength;
  71. //
  72. // The number of bytes remaining in the current chunk.
  73. //
  74. ULONGLONG BytesLeftInChunk;
  75. //
  76. // Is this chunk encoded?
  77. //
  78. ULONG Chunked:1;
  79. ULONG :3; // makes debugging easier
  80. //
  81. // Is this the last chunk?
  82. //
  83. ULONG LastChunk:1;
  84. ULONG :3; // makes debugging easier
  85. //
  86. // Is the port number in the host?
  87. //
  88. ULONG PortInHost:1;
  89. ULONG :3; // makes debugging easier
  90. struct
  91. {
  92. //
  93. // The raw URL.
  94. //
  95. // All of the following pointers point into pUrl.
  96. //
  97. PUCHAR pUrl;
  98. //
  99. // Host part, if any.
  100. //
  101. PUCHAR pHost;
  102. //
  103. // Pointer to the absolute path part.
  104. //
  105. PUCHAR pAbsPath;
  106. //
  107. // Length of the raw URL.
  108. //
  109. ULONG Length;
  110. } RawUrl;
  111. struct
  112. {
  113. //
  114. // The canonicalized, fully qualified URL.
  115. //
  116. // All of the following pointers point into pUrl.
  117. //
  118. PWSTR pUrl;
  119. //
  120. // Pointer to the host part.
  121. //
  122. PWSTR pHost;
  123. //
  124. // Pointer to the absolute path part.
  125. //
  126. PWSTR pAbsPath;
  127. //
  128. // Pointer to the query string, if any.
  129. //
  130. PWSTR pQueryString;
  131. //
  132. // The entire length (in bytes).
  133. //
  134. ULONG Length;
  135. //
  136. // The hash of the entire fully qualified URL.
  137. //
  138. ULONG Hash;
  139. } CookedUrl;
  140. //
  141. // Pointer to the local transport address for the network connection.
  142. //
  143. PTRANSPORT_ADDRESS pLocalAddress;
  144. } HTTP_PARSE_INFO, *PHTTP_PARSE_INFO;
  145. Imports needed by the parser:
  146. Pool stuff w/ usual debug support
  147. KeGetCurrentIrql()
  148. #ifdef UL_KERNEL_RUNTIME
  149. #define UL_GET_CURRENT_IRQL() KeGetCurrentIrql()
  150. #else
  151. #define UL_GET_CURRENT_IRQL() 0
  152. //
  153. // Types stolen from ntos\inc\ex.h.
  154. //
  155. typedef enum _POOL_TYPE
  156. {
  157. NonPagedPool,
  158. PagedPool,
  159. NonPagedPoolMustSucceed,
  160. DontUseThisType,
  161. NonPagedPoolCacheAligned,
  162. PagedPoolCacheAligned,
  163. NonPagedPoolCacheAlignedMustS,
  164. MaxPoolType
  165. // end_wdm
  166. ,
  167. //
  168. // Note these per session types are carefully chosen so that the appropriate
  169. // masking still applies as well as MaxPoolType above.
  170. //
  171. NonPagedPoolSession = 32,
  172. PagedPoolSession = NonPagedPoolSession + 1,
  173. NonPagedPoolMustSucceedSession = PagedPoolSession + 1,
  174. DontUseThisTypeSession = NonPagedPoolMustSucceedSession + 1,
  175. NonPagedPoolCacheAlignedSession = DontUseThisTypeSession + 1,
  176. PagedPoolCacheAlignedSession = NonPagedPoolCacheAlignedSession + 1,
  177. NonPagedPoolCacheAlignedMustSSession = PagedPoolCacheAlignedSession + 1,
  178. } POOL_TYPE;
  179. #endif
  180. Pool tags used in the parser:
  181. HTTP_UNKNOWN_HEADER_POOL_TAG
  182. URL_POOL_TAG
  183. HEADER_VALUE_POOL_TAG
  184. typedef
  185. PVOID
  186. (NTAPI * PFN_MEM_ALLOC)(
  187. IN POOL_TYPE PoolType,
  188. IN ULONG NumberOfBytes,
  189. IN ULONG Tag,
  190. #if DBG
  191. ,
  192. IN PSTR pFileName,
  193. IN ULONG LineNumber
  194. #endif
  195. );
  196. typedef
  197. VOID
  198. (NTAPI * PFN_MEM_FREE)(
  199. IN PVOID pBuffer,
  200. IN ULONG Tag
  201. );
  202. typedef
  203. VOID
  204. (NTAPI * PFN_ASSERT)(
  205. IN PVOID pFailedAssertion,
  206. IN PVOID pFileName,
  207. IN ULONG LineNumber,
  208. IN PSTR pMessage
  209. );
  210. typedef struct _UL_PARSER_ENVIRONMENT
  211. {
  212. PFN_MEM_ALLOC pAllocRoutine;
  213. PFN_MEM_FREE pFreeRoutine;
  214. PFN_ASSERT pAssertRoutine;
  215. ULONG UrlPoolTag;
  216. ULONG HeaderValuePoolTag;
  217. ULONG UnknownHeaderPoolTag;
  218. } UL_PARSER_ENVIRONMENT, *PUL_PARSER_ENVIRONMENT;
  219. NTSTATUS
  220. UlInitializeParser(
  221. IN PUL_PARSER_ENVIRONMENT pEnvironment
  222. );
  223. VOID
  224. UlTerminateParser(
  225. VOID
  226. );
  227. NTSTATUS
  228. UlInitializeParseInfo(
  229. OUT PHTTP_PARSE_INFO pParseInfo,
  230. IN PTRANSPORT_ADDRESS pLocalAddress
  231. );
  232. VOID
  233. UlDestroyParseInfo(
  234. IN OUT PHTTP_PARSE_INFO pParseInfo
  235. );
  236. NTSTATUS
  237. UlParseHttp(
  238. IN OUT PHTTP_PARSE_INFO pParseInfo,
  239. IN PUCHAR pHttpRequest,
  240. IN ULONG HttpRequestLength,
  241. OUT PULONG pBytesTaken
  242. );
  243. NTSTATUS
  244. UlBuildUserRequest(
  245. OUT PUL_HTTP_REQUEST pHttpRequest,
  246. IN PHTTP_PARSE_INFO pParseInfo,
  247. IN UL_HTTP_CONNECTION_ID ConnectionId,
  248. IN UL_HTTP_REQUEST_ID RequestId,
  249. IN UL_URL_CONTEXT UrlContext,
  250. IN UL_REQUEST_REASON RequestReason
  251. );
  252. NTSTATUS status;
  253. UL_PARSER_ENVIRONMENT env;
  254. #if DBG
  255. env.pAllocRoutine = &UlAllocatePool;
  256. env.pFreeRoutine = &UlFreePool;
  257. #else
  258. env.pAllocRoutine = &ExAllocatePoolWithTag;
  259. #if USE_FREE_POOL_WITH_TAG
  260. env.pFreeRoutine = &ExFreePoolWithTag;
  261. #else
  262. env.pFreeRoutine = &UlpFreePoolWithTag;
  263. #endif
  264. #endif
  265. env.pAssertRoutine = &RtlAssert;
  266. env.UrlPoolTag = URL_POOL_TAG;
  267. env.HeaderValuePoolTag = HEADER_VALUE_POOL_TAG;
  268. env.UnknownHeaderPoolTag = HTTP_UNKNOWN_HEADER_POOL_TAG;
  269. status = UlInitializeParser( &env );
  270. if (!NT_SUCCESS(status))
  271. {
  272. // Oh no! ...
  273. }
  274. #if DBG
  275. #define UL_ALLOCATE_POOL(a,b,t,p) \
  276. (g_Environment.pAllocRoutine)( \
  277. (a), \
  278. (b), \
  279. (t), \
  280. (p) \
  281. )
  282. #else
  283. #define UL_ALLOCATE_POOL(a,b,t,p) \
  284. (g_Environment.pAllocRoutine)( \
  285. (a), \
  286. (b), \
  287. (t), \
  288. (p), \
  289. __FILE__, \
  290. __LINE__ \
  291. )
  292. #endif
  293. #define UL_FREE_POOL(a,t) \
  294. (g_Environment.pFreeRoutine)( \
  295. (a), \
  296. (t) \
  297. )
  298. #define UL_ASSERT(exp) \
  299. (g_Environment.pAssertRoutine)( \
  300. #exp, \
  301. __FILE__, \
  302. __LINE__, \
  303. NULL \
  304. );