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.

1178 lines
27 KiB

  1. /*++
  2. Copyright (c) 1998-1999 Microsoft Corporation
  3. Module Name:
  4. misc.c
  5. Abstract:
  6. This module contains the miscellaneous UL routines.
  7. Author:
  8. Keith Moore (keithmo) 10-Jun-1998
  9. Revision History:
  10. --*/
  11. #include "precomp.h"
  12. ULONG HttpChars[256];
  13. //
  14. // Private prototypes.
  15. //
  16. NTSTATUS
  17. UlpRestartDeviceControl(
  18. IN PDEVICE_OBJECT pDeviceObject,
  19. IN PIRP pIrp,
  20. IN PVOID pContext
  21. );
  22. #define FIXUP_PTR( Type, pUserPtr, pKernelPtr, pOffsetPtr, BufferLength ) \
  23. (Type) ((PUCHAR)(pUserPtr) + DIFF((PUCHAR)(pOffsetPtr) - (PUCHAR)(pKernelPtr)))
  24. #ifdef ALLOC_PRAGMA
  25. #endif // ALLOC_PRAGMA
  26. #if 0
  27. NOT PAGEABLE -- UlULongLongToAscii
  28. #endif
  29. //
  30. // Public functions.
  31. //
  32. /***************************************************************************++
  33. Routine Description:
  34. Converts the given ULONGLLONG to an ASCII representation and stores it
  35. in the given string.
  36. Arguments:
  37. String - Receives the ASCII representation of the ULONGLONG.
  38. Value - Supplies the ULONGLONG to convert.
  39. Return Value:
  40. PSTR - Pointer to the next character in String *after* the converted
  41. ULONGLONG.
  42. --***************************************************************************/
  43. PSTR
  44. UlULongLongToAscii(
  45. IN PSTR String,
  46. IN ULONGLONG Value
  47. )
  48. {
  49. PSTR p1;
  50. PSTR p2;
  51. CHAR ch;
  52. ULONG digit;
  53. //
  54. // Special case 0 to make the rest of the routine simpler.
  55. //
  56. if (Value == 0)
  57. {
  58. *String++ = '0';
  59. }
  60. else
  61. {
  62. //
  63. // Convert the ULONG. Note that this will result in the string
  64. // being backwards in memory.
  65. //
  66. p1 = String;
  67. p2 = String;
  68. while (Value != 0)
  69. {
  70. digit = (ULONG)( Value % 10 );
  71. Value = Value / 10;
  72. *p1++ = '0' + (CHAR)digit;
  73. }
  74. //
  75. // Reverse the string.
  76. //
  77. String = p1;
  78. p1--;
  79. while (p1 > p2)
  80. {
  81. ch = *p1;
  82. *p1 = *p2;
  83. *p2 = ch;
  84. p2++;
  85. p1--;
  86. }
  87. }
  88. *String = '\0';
  89. return String;
  90. } // UlULongLongToAscii
  91. NTSTATUS
  92. _RtlIntegerToUnicode(
  93. IN ULONG Value,
  94. IN ULONG Base OPTIONAL,
  95. IN LONG BufferLength,
  96. OUT PWSTR String
  97. )
  98. {
  99. PWSTR p1;
  100. PWSTR p2;
  101. WCHAR ch;
  102. ULONG digit;
  103. //
  104. // Special case 0 to make the rest of the routine simpler.
  105. //
  106. if (Value == 0)
  107. {
  108. *String++ = L'0';
  109. }
  110. else
  111. {
  112. //
  113. // Convert the ULONG. Note that this will result in the string
  114. // being backwards in memory.
  115. //
  116. p1 = String;
  117. p2 = String;
  118. while (Value != 0)
  119. {
  120. digit = (ULONG)( Value % 10 );
  121. Value = Value / 10;
  122. *p1++ = L'0' + (WCHAR)digit;
  123. }
  124. //
  125. // Reverse the string.
  126. //
  127. String = p1;
  128. p1--;
  129. while (p1 > p2)
  130. {
  131. ch = *p1;
  132. *p1 = *p2;
  133. *p2 = ch;
  134. p2++;
  135. p1--;
  136. }
  137. }
  138. *String = L'\0';
  139. return STATUS_SUCCESS;
  140. } // _RtlIntegerToUnicode
  141. /***************************************************************************++
  142. Routine Description:
  143. Converts an ansi string to an integer. fails if any non-digit characters
  144. appears in the string. fails on negative numbers, and assumes no preceding
  145. spaces.
  146. Arguments:
  147. PUCHAR pString the string to convert
  148. ULONG Base the base, must be 10 or 16
  149. PULONG pValue the return value of the converted integer
  150. Return Value:
  151. NTSTATUS - Completion status.
  152. --***************************************************************************/
  153. NTSTATUS
  154. UlAnsiToULongLong(
  155. PUCHAR pString,
  156. ULONG Base,
  157. PULONGLONG pValue
  158. )
  159. {
  160. ULONGLONG Value;
  161. ULONGLONG NewValue;
  162. if (Base != 10 && Base != 16)
  163. RETURN(STATUS_INVALID_PARAMETER);
  164. //
  165. // No preceding space, we already skipped it
  166. //
  167. ASSERT(IS_HTTP_LWS(pString[0]) == FALSE);
  168. Value = 0;
  169. while (pString[0] != ANSI_NULL)
  170. {
  171. if (
  172. (Base == 10 && IS_HTTP_DIGIT(pString[0]) == FALSE) ||
  173. (Base == 16 && IS_HTTP_HEX(pString[0]) == FALSE)
  174. )
  175. {
  176. //
  177. // Not valid , bad!
  178. //
  179. RETURN(STATUS_INVALID_PARAMETER);
  180. }
  181. if (Base == 16)
  182. {
  183. if (IS_HTTP_ALPHA(pString[0]))
  184. {
  185. NewValue = 16 * Value + (UPCASE_CHAR(pString[0]) - 'A' + 10);
  186. }
  187. else
  188. {
  189. NewValue = 16 * Value + (pString[0] - '0');
  190. }
  191. }
  192. else
  193. {
  194. NewValue = 10 * Value + (pString[0] - '0');
  195. }
  196. if (NewValue < Value)
  197. {
  198. //
  199. // Very bad... we overflew
  200. //
  201. RETURN(STATUS_SECTION_TOO_BIG);
  202. }
  203. Value = NewValue;
  204. pString += 1;
  205. }
  206. *pValue = Value;
  207. return STATUS_SUCCESS;
  208. } // UlAnsiToULongLong
  209. /***************************************************************************++
  210. Routine Description:
  211. Converts a unicode string to an integer. fails if any non-digit characters
  212. appear in the string. fails on negative numbers, and assumes no preceding
  213. spaces.
  214. Arguments:
  215. PWCHAR pString the string to convert
  216. ULONG Base the base, must be 10 or 16
  217. PULONG pValue the return value of the converted integer
  218. Return Value:
  219. NTSTATUS - Completion status.
  220. --***************************************************************************/
  221. NTSTATUS
  222. UlUnicodeToULongLong(
  223. PWCHAR pString,
  224. ULONG Base,
  225. PULONGLONG pValue
  226. )
  227. {
  228. ULONGLONG Value;
  229. ULONGLONG NewValue;
  230. if (Base != 10 && Base != 16)
  231. RETURN(STATUS_INVALID_PARAMETER);
  232. //
  233. // No preceding space, we already skipped it
  234. //
  235. ASSERT(pString[0] < 128 && IS_HTTP_LWS(pString[0]) == FALSE);
  236. Value = 0;
  237. while (pString[0] != UNICODE_NULL)
  238. {
  239. if ((Base == 10 &&
  240. (pString[0] >= 128 || IS_HTTP_DIGIT(pString[0]) == FALSE)) ||
  241. (Base == 16 &&
  242. (pString[0] >= 128 || IS_HTTP_HEX(pString[0]) == FALSE)))
  243. {
  244. //
  245. // Not valid , bad!
  246. //
  247. RETURN(STATUS_INVALID_PARAMETER);
  248. }
  249. if (Base == 16)
  250. {
  251. if (IS_HTTP_ALPHA(pString[0]))
  252. {
  253. NewValue = 16 * Value + (pString[0] - L'A' + 10);
  254. }
  255. else
  256. {
  257. NewValue = 16 * Value + (pString[0] - L'0');
  258. }
  259. }
  260. else
  261. {
  262. NewValue = 10 * Value + (pString[0] - L'0');
  263. }
  264. if (NewValue < Value)
  265. {
  266. //
  267. // Very bad... we overflew
  268. //
  269. RETURN(STATUS_INVALID_PARAMETER);
  270. }
  271. Value = NewValue;
  272. pString += 1;
  273. }
  274. *pValue = Value;
  275. return STATUS_SUCCESS;
  276. } // UlUnicodeToULongLong
  277. //
  278. // Private routines.
  279. //
  280. /*++
  281. Routine Description:
  282. Routine to initialize the utilitu code.
  283. Arguments:
  284. Return Value:
  285. --*/
  286. NTSTATUS
  287. InitializeHttpUtil(
  288. VOID
  289. )
  290. {
  291. ULONG i;
  292. // Initialize the HttpChars array appropriately.
  293. for (i = 0; i < 128; i++)
  294. {
  295. HttpChars[i] = HTTP_CHAR;
  296. }
  297. for (i = 'A'; i <= 'Z'; i++)
  298. {
  299. HttpChars[i] |= HTTP_UPCASE;
  300. }
  301. for (i = 'a'; i <= 'z'; i++)
  302. {
  303. HttpChars[i] |= HTTP_LOCASE;
  304. }
  305. for (i = '0'; i <= '9'; i++)
  306. {
  307. HttpChars[i] |= (HTTP_DIGIT | HTTP_HEX);
  308. }
  309. for (i = 0; i <= 31; i++)
  310. {
  311. HttpChars[i] |= HTTP_CTL;
  312. }
  313. HttpChars[127] |= HTTP_CTL;
  314. HttpChars[SP] |= HTTP_LWS;
  315. HttpChars[HT] |= HTTP_LWS;
  316. for (i = 'A'; i <= 'F'; i++)
  317. {
  318. HttpChars[i] |= HTTP_HEX;
  319. }
  320. for (i = 'a'; i <= 'f'; i++)
  321. {
  322. HttpChars[i] |= HTTP_HEX;
  323. }
  324. HttpChars['('] |= HTTP_SEPERATOR;
  325. HttpChars[')'] |= HTTP_SEPERATOR;
  326. HttpChars['<'] |= HTTP_SEPERATOR;
  327. HttpChars['>'] |= HTTP_SEPERATOR;
  328. HttpChars['@'] |= HTTP_SEPERATOR;
  329. HttpChars[','] |= HTTP_SEPERATOR;
  330. HttpChars[';'] |= HTTP_SEPERATOR;
  331. HttpChars[':'] |= HTTP_SEPERATOR;
  332. HttpChars['\\'] |= HTTP_SEPERATOR;
  333. HttpChars['"'] |= HTTP_SEPERATOR;
  334. HttpChars['/'] |= HTTP_SEPERATOR;
  335. HttpChars['['] |= HTTP_SEPERATOR;
  336. HttpChars[']'] |= HTTP_SEPERATOR;
  337. HttpChars['?'] |= HTTP_SEPERATOR;
  338. HttpChars['='] |= HTTP_SEPERATOR;
  339. HttpChars['{'] |= HTTP_SEPERATOR;
  340. HttpChars['}'] |= HTTP_SEPERATOR;
  341. HttpChars[SP] |= HTTP_SEPERATOR;
  342. HttpChars[HT] |= HTTP_SEPERATOR;
  343. //
  344. // URL "reserved" characters (rfc2396)
  345. //
  346. HttpChars[';'] |= URL_LEGAL;
  347. HttpChars['/'] |= URL_LEGAL;
  348. HttpChars['\\'] |= URL_LEGAL;
  349. HttpChars['?'] |= URL_LEGAL;
  350. HttpChars[':'] |= URL_LEGAL;
  351. HttpChars['@'] |= URL_LEGAL;
  352. HttpChars['&'] |= URL_LEGAL;
  353. HttpChars['='] |= URL_LEGAL;
  354. HttpChars['+'] |= URL_LEGAL;
  355. HttpChars['$'] |= URL_LEGAL;
  356. HttpChars[','] |= URL_LEGAL;
  357. //
  358. // URL escape character
  359. //
  360. HttpChars['%'] |= URL_LEGAL;
  361. //
  362. // URL "mark" characters (rfc2396)
  363. //
  364. HttpChars['-'] |= URL_LEGAL;
  365. HttpChars['_'] |= URL_LEGAL;
  366. HttpChars['.'] |= URL_LEGAL;
  367. HttpChars['!'] |= URL_LEGAL;
  368. HttpChars['~'] |= URL_LEGAL;
  369. HttpChars['*'] |= URL_LEGAL;
  370. HttpChars['\''] |= URL_LEGAL;
  371. HttpChars['('] |= URL_LEGAL;
  372. HttpChars[')'] |= URL_LEGAL;
  373. for (i = 0; i < 128; i++)
  374. {
  375. if (!IS_HTTP_SEPERATOR(i) && !IS_HTTP_CTL(i))
  376. {
  377. HttpChars[i] |= HTTP_TOKEN;
  378. }
  379. }
  380. return STATUS_SUCCESS;
  381. }
  382. //
  383. // constants used by the date formatter
  384. //
  385. const PWSTR pDays[] =
  386. {
  387. L"Sun", L"Mon", L"Tue", L"Wed", L"Thu", L"Fri", L"Sat"
  388. };
  389. const PWSTR pMonths[] =
  390. {
  391. L"Jan", L"Feb", L"Mar", L"Apr", L"May", L"Jun", L"Jul",
  392. L"Aug", L"Sep", L"Oct", L"Nov", L"Dec"
  393. };
  394. __inline
  395. VOID
  396. TwoDigitsToUnicode(
  397. PWSTR pBuffer,
  398. ULONG Number
  399. )
  400. {
  401. pBuffer[0] = L'0' + (WCHAR)(Number / 10);
  402. pBuffer[1] = L'0' + (WCHAR)(Number % 10);
  403. }
  404. /***************************************************************************++
  405. Routine Description:
  406. Converts the given system time to string representation containing
  407. GMT Formatted String.
  408. Arguments:
  409. pTime - System time that needs to be converted.
  410. pBuffer - pointer to string which will contain the GMT time on
  411. successful return.
  412. BufferLength - size of pszBuff in bytes
  413. Return Value:
  414. NTSTATUS
  415. History:
  416. MuraliK 3-Jan-1995
  417. paulmcd 4-Mar-1999 copied to ul
  418. --***************************************************************************/
  419. NTSTATUS
  420. TimeFieldsToHttpDate(
  421. IN PTIME_FIELDS pTime,
  422. OUT PWSTR pBuffer,
  423. IN ULONG BufferLength
  424. )
  425. {
  426. NTSTATUS Status;
  427. ASSERT(pBuffer != NULL);
  428. if (BufferLength < (HTTP_DATE_COUNT + 1)*sizeof(WCHAR))
  429. {
  430. return STATUS_BUFFER_TOO_SMALL;
  431. }
  432. // 0 1 2
  433. // 01234567890123456789012345678
  434. // Formats a string like: "Thu, 14 Jul 1994 15:26:05 GMT"
  435. //
  436. //
  437. // write the constants
  438. //
  439. pBuffer[3] = L',';
  440. pBuffer[4] = pBuffer[7] = pBuffer[11] = L' ';
  441. pBuffer[19] = pBuffer[22] = L':';
  442. //
  443. // now the variants
  444. //
  445. //
  446. // 0-based Weekday
  447. //
  448. RtlCopyMemory(&(pBuffer[0]), pDays[pTime->Weekday], 3*sizeof(WCHAR));
  449. TwoDigitsToUnicode(&(pBuffer[5]), pTime->Day);
  450. //
  451. // 1-based Month
  452. //
  453. RtlCopyMemory(&(pBuffer[8]), pMonths[pTime->Month - 1], 3*sizeof(WCHAR)); // 1-based
  454. Status = _RtlIntegerToUnicode(pTime->Year, 10, 5, &(pBuffer[12]));
  455. ASSERT(NT_SUCCESS(Status));
  456. pBuffer[16] = L' ';
  457. TwoDigitsToUnicode(&(pBuffer[17]), pTime->Hour);
  458. TwoDigitsToUnicode(&(pBuffer[20]), pTime->Minute);
  459. TwoDigitsToUnicode(&(pBuffer[23]), pTime->Second);
  460. RtlCopyMemory(&(pBuffer[25]), L" GMT", sizeof(L" GMT"));
  461. return STATUS_SUCCESS;
  462. } // TimeFieldsToHttpDate
  463. ULONG
  464. _MultiByteToWideCharWin9x(
  465. ULONG uCodePage,
  466. ULONG dwFlags,
  467. PCSTR lpMultiByteStr,
  468. int cchMultiByte,
  469. PWSTR lpWideCharStr,
  470. int cchWideChar
  471. )
  472. {
  473. int i;
  474. //
  475. // simply add a 0 upper byte, it's supposed to be ascii
  476. //
  477. for (i = 0; i < cchMultiByte; ++i)
  478. {
  479. if (lpMultiByteStr[i] > 128)
  480. {
  481. lpWideCharStr[i] = (WCHAR)('_'); // (WCHAR)(DefaultChar);
  482. }
  483. else
  484. {
  485. lpWideCharStr[i] = (WCHAR)(lpMultiByteStr[i]);
  486. }
  487. }
  488. return (ULONG)(i);
  489. } // _MultiByteToWideCharWin9x
  490. /******************************************************************************
  491. Routine Description:
  492. Copy an HTTP request to a buffer.
  493. Arguments:
  494. pRequest - Pointer to this request.
  495. pBuffer - Pointer to buffer where we'll copy.
  496. BufferLength - Length of pBuffer.
  497. pEntityBody - Pointer to entity body of request.
  498. EntityBodyLength - Length of entity body.
  499. Return Value:
  500. ******************************************************************************/
  501. NTSTATUS
  502. UlpHttpRequestToBufferWin9x(
  503. PUL_INTERNAL_REQUEST pRequest,
  504. PUCHAR pKernelBuffer,
  505. ULONG BufferLength,
  506. PUCHAR pEntityBody,
  507. ULONG EntityBodyLength,
  508. ULONG ulLocalIPAddress,
  509. USHORT ulLocalPort,
  510. ULONG ulRemoteIPAddress,
  511. USHORT ulRemotePort
  512. )
  513. {
  514. PHTTP_REQUEST pHttpRequest;
  515. PHTTP_UNKNOWN_HEADER pUserCurrentUnknownHeader;
  516. PUCHAR pCurrentBufferPtr;
  517. ULONG i;
  518. ULONG BytesCopied;
  519. ULONG HeaderCount = 0;
  520. PVOID pUserBuffer;
  521. PHTTP_NETWORK_ADDRESS_IPV4 pLocalAddress;
  522. PHTTP_NETWORK_ADDRESS_IPV4 pRemoteAddress;
  523. //
  524. // Sanity check.
  525. //
  526. PAGED_CODE();
  527. ASSERT(IS_VALID_HTTP_REQUEST(pRequest));
  528. ASSERT(pKernelBuffer != NULL);
  529. ASSERT(BufferLength > sizeof(HTTP_REQUEST));
  530. // BUGBUG - this is used for the pointer fixups
  531. // don't know what you want to set this to
  532. // MAUROOT - NULL should be ok.
  533. pUserBuffer = NULL;
  534. //
  535. // wipe it clean
  536. //
  537. RtlZeroMemory( pKernelBuffer, sizeof(HTTP_REQUEST) );
  538. //
  539. // Set up our pointers to the HTTP_REQUEST structure, the
  540. // header arrays we're going to fill in, and the pointer to
  541. // where we're going to start filling them in.
  542. //
  543. // CODEWORK: Make this transport independent.
  544. //
  545. pHttpRequest = (PHTTP_REQUEST)pKernelBuffer;
  546. pLocalAddress = (PHTTP_NETWORK_ADDRESS_IPV4)( pHttpRequest + 1 );
  547. pRemoteAddress = pLocalAddress + 1;
  548. pUserCurrentUnknownHeader = (PHTTP_UNKNOWN_HEADER)( pRemoteAddress + 1 );
  549. pCurrentBufferPtr = (PUCHAR)(pUserCurrentUnknownHeader +
  550. pRequest->UnknownHeaderCount);
  551. //
  552. // Now fill in the HTTP request structure.
  553. //
  554. pHttpRequest->ConnectionId = pRequest->ConnectionId;
  555. pHttpRequest->RequestId = pRequest->RequestId;
  556. // BUGBUG - Don't know where you'll come up with this
  557. // pHttpRequest->UrlContext = pRequest->pConfigGroup->UrlContext;
  558. // MAUROOT - NULL should be ok.
  559. pHttpRequest->UrlContext = 0;
  560. pHttpRequest->Version = pRequest->Version;
  561. pHttpRequest->Verb = pRequest->Verb;
  562. pHttpRequest->Reason = pRequest->Reason;
  563. pHttpRequest->Address.RemoteAddressLength = sizeof(HTTP_NETWORK_ADDRESS_IPV4);
  564. pHttpRequest->Address.RemoteAddressType = HTTP_NETWORK_ADDRESS_TYPE_IPV4;
  565. pHttpRequest->Address.pRemoteAddress = FIXUP_PTR(
  566. PVOID,
  567. pUserBuffer,
  568. pKernelBuffer,
  569. pRemoteAddress,
  570. BufferLength
  571. );
  572. pRemoteAddress->IpAddress = SWAP_LONG( ulRemoteIPAddress );
  573. pRemoteAddress->Port = SWAP_SHORT( ulRemotePort );
  574. pHttpRequest->Address.LocalAddressLength = sizeof(HTTP_NETWORK_ADDRESS_IPV4);
  575. pHttpRequest->Address.LocalAddressType = HTTP_NETWORK_ADDRESS_TYPE_IPV4;
  576. pHttpRequest->Address.pLocalAddress = FIXUP_PTR(
  577. PVOID,
  578. pUserBuffer,
  579. pKernelBuffer,
  580. pLocalAddress,
  581. BufferLength
  582. );
  583. pLocalAddress->IpAddress = SWAP_LONG( ulLocalIPAddress );
  584. pLocalAddress->Port = SWAP_SHORT( ulLocalPort );
  585. //
  586. // any raw verb?
  587. //
  588. if (pRequest->Verb == HttpVerbUnknown)
  589. {
  590. //
  591. // Need to copy in the raw verb for the client.
  592. //
  593. ASSERT(pRequest->RawVerbLength <= 0x7fff);
  594. pHttpRequest->UnknownVerbLength = (USHORT)(pRequest->RawVerbLength * sizeof(CHAR));
  595. pHttpRequest->pUnknownVerb = FIXUP_PTR(
  596. PSTR,
  597. pUserBuffer,
  598. pKernelBuffer,
  599. pCurrentBufferPtr,
  600. BufferLength
  601. );
  602. RtlCopyMemory(
  603. pCurrentBufferPtr,
  604. pRequest->pRawVerb,
  605. pRequest->RawVerbLength
  606. );
  607. pCurrentBufferPtr += pRequest->RawVerbLength;
  608. //
  609. // terminate it
  610. //
  611. ((PSTR)pCurrentBufferPtr)[0] = ANSI_NULL;
  612. pCurrentBufferPtr += sizeof(CHAR);
  613. }
  614. //
  615. // copy the raw url
  616. //
  617. ASSERT(pRequest->RawUrl.Length <= 0x7fff);
  618. pHttpRequest->RawUrlLength = (USHORT)(pRequest->RawUrl.Length * sizeof(CHAR));
  619. pHttpRequest->pRawUrl = FIXUP_PTR(
  620. PSTR,
  621. pUserBuffer,
  622. pKernelBuffer,
  623. pCurrentBufferPtr,
  624. BufferLength
  625. );
  626. RtlCopyMemory(
  627. pCurrentBufferPtr,
  628. pRequest->RawUrl.pUrl,
  629. pRequest->RawUrl.Length
  630. );
  631. pCurrentBufferPtr += pRequest->RawUrl.Length;
  632. //
  633. // terminate it
  634. //
  635. ((PSTR)pCurrentBufferPtr)[0] = ANSI_NULL;
  636. pCurrentBufferPtr += sizeof(CHAR);
  637. //
  638. // and now the cooked url sections
  639. //
  640. //
  641. // make sure they are valid
  642. //
  643. ASSERT(pRequest->CookedUrl.pUrl != NULL);
  644. ASSERT(pRequest->CookedUrl.pHost != NULL);
  645. ASSERT(pRequest->CookedUrl.pAbsPath != NULL);
  646. //
  647. // do the full url
  648. //
  649. ASSERT(pRequest->CookedUrl.Length <= 0xffff);
  650. pHttpRequest->CookedUrl.FullUrlLength = (USHORT)(pRequest->CookedUrl.Length);
  651. pHttpRequest->CookedUrl.pFullUrl = FIXUP_PTR(
  652. PWSTR,
  653. pUserBuffer,
  654. pKernelBuffer,
  655. pCurrentBufferPtr,
  656. BufferLength
  657. );
  658. //
  659. // and the host
  660. //
  661. pHttpRequest->CookedUrl.HostLength = DIFF(pRequest->CookedUrl.pAbsPath - pRequest->CookedUrl.pHost)
  662. * sizeof(WCHAR);
  663. pHttpRequest->CookedUrl.pHost = pHttpRequest->CookedUrl.pFullUrl +
  664. DIFF(pRequest->CookedUrl.pHost - pRequest->CookedUrl.pUrl);
  665. //
  666. // is there a query string?
  667. //
  668. if (pRequest->CookedUrl.pQueryString != NULL)
  669. {
  670. pHttpRequest->CookedUrl.AbsPathLength = DIFF(pRequest->CookedUrl.pQueryString -
  671. pRequest->CookedUrl.pAbsPath) * sizeof(WCHAR);
  672. pHttpRequest->CookedUrl.pAbsPath = pHttpRequest->CookedUrl.pHost +
  673. (pHttpRequest->CookedUrl.HostLength / sizeof(WCHAR));
  674. pHttpRequest->CookedUrl.QueryStringLength = (USHORT)(pRequest->CookedUrl.Length) - (
  675. DIFF(
  676. pRequest->CookedUrl.pQueryString -
  677. pRequest->CookedUrl.pUrl
  678. ) * sizeof(WCHAR)
  679. );
  680. pHttpRequest->CookedUrl.pQueryString = pHttpRequest->CookedUrl.pAbsPath +
  681. (pHttpRequest->CookedUrl.AbsPathLength / sizeof(WCHAR));
  682. }
  683. else
  684. {
  685. pHttpRequest->CookedUrl.AbsPathLength = (USHORT)(pRequest->CookedUrl.Length) - (
  686. DIFF(
  687. pRequest->CookedUrl.pAbsPath -
  688. pRequest->CookedUrl.pUrl
  689. ) * sizeof(WCHAR)
  690. );
  691. pHttpRequest->CookedUrl.pAbsPath = pHttpRequest->CookedUrl.pHost +
  692. (pHttpRequest->CookedUrl.HostLength / sizeof(WCHAR));
  693. pHttpRequest->CookedUrl.QueryStringLength = 0;
  694. pHttpRequest->CookedUrl.pQueryString = NULL;
  695. }
  696. //
  697. // copy the full url
  698. //
  699. RtlCopyMemory(
  700. pCurrentBufferPtr,
  701. pRequest->CookedUrl.pUrl,
  702. pRequest->CookedUrl.Length
  703. );
  704. pCurrentBufferPtr += pRequest->CookedUrl.Length;
  705. //
  706. // terminate it
  707. //
  708. ((PWSTR)pCurrentBufferPtr)[0] = UNICODE_NULL;
  709. pCurrentBufferPtr += sizeof(WCHAR);
  710. //
  711. // no entity body, CODEWORK.
  712. //
  713. if (pRequest->ContentLength > 0 || pRequest->Chunked == 1)
  714. {
  715. pHttpRequest->MoreEntityBodyExists = 1;
  716. }
  717. else
  718. {
  719. pHttpRequest->MoreEntityBodyExists = 0;
  720. }
  721. pHttpRequest->EntityChunkCount = 0;
  722. pHttpRequest->pEntityChunks = NULL;
  723. //
  724. // Copy in the known headers.
  725. //
  726. // Loop through the known header array in the HTTP connection,
  727. // and copy any that we have.
  728. //
  729. for (i = 0; i < HttpHeaderRequestMaximum; i++)
  730. {
  731. if (pRequest->Headers[i].Valid == 1)
  732. {
  733. //
  734. // Have a header here we need to copy in.
  735. //
  736. ASSERT(pRequest->Headers[i].HeaderLength <= 0x7fff);
  737. //
  738. // ok for HeaderLength to be 0 . we will give usermode a pointer
  739. // pointing to a NULL string. RawValueLength will be 0.
  740. //
  741. pHttpRequest->Headers.pKnownHeaders[i].RawValueLength =
  742. (USHORT)(pRequest->Headers[i].HeaderLength * sizeof(CHAR));
  743. pHttpRequest->Headers.pKnownHeaders[i].pRawValue =
  744. FIXUP_PTR(
  745. PSTR,
  746. pUserBuffer,
  747. pKernelBuffer,
  748. pCurrentBufferPtr,
  749. BufferLength
  750. );
  751. RtlCopyMemory(
  752. pCurrentBufferPtr,
  753. pRequest->Headers[i].pHeader,
  754. pRequest->Headers[i].HeaderLength
  755. );
  756. pCurrentBufferPtr += pRequest->Headers[i].HeaderLength;
  757. //
  758. // terminate it
  759. //
  760. ((PSTR)pCurrentBufferPtr)[0] = ANSI_NULL;
  761. pCurrentBufferPtr += sizeof(CHAR);
  762. }
  763. else
  764. {
  765. pHttpRequest->Headers.pKnownHeaders[i].RawValueLength = 0;
  766. pHttpRequest->Headers.pKnownHeaders[i].pRawValue = NULL;
  767. }
  768. }
  769. //
  770. // Now loop through the unknown headers, and copy them in.
  771. //
  772. pHttpRequest->Headers.UnknownHeaderCount = pRequest->UnknownHeaderCount;
  773. if (pRequest->UnknownHeaderCount == 0)
  774. {
  775. pHttpRequest->Headers.pUnknownHeaders = NULL;
  776. }
  777. else
  778. {
  779. pHttpRequest->Headers.pUnknownHeaders =
  780. FIXUP_PTR(
  781. PHTTP_UNKNOWN_HEADER,
  782. pUserBuffer,
  783. pKernelBuffer,
  784. pUserCurrentUnknownHeader,
  785. BufferLength
  786. );
  787. }
  788. while (!IsListEmpty(&pRequest->UnknownHeaderList))
  789. {
  790. PUL_HTTP_UNKNOWN_HEADER pUnknownHeader;
  791. PLIST_ENTRY pListEntry;
  792. pListEntry = RemoveHeadList(&pRequest->UnknownHeaderList);
  793. pListEntry->Flink = pListEntry->Blink = NULL;
  794. pUnknownHeader = CONTAINING_RECORD(
  795. pListEntry,
  796. UL_HTTP_UNKNOWN_HEADER,
  797. List
  798. );
  799. HeaderCount++;
  800. ASSERT(HeaderCount <= pRequest->UnknownHeaderCount);
  801. //
  802. // First copy in the header name.
  803. //
  804. pUserCurrentUnknownHeader->NameLength = (USHORT)
  805. pUnknownHeader->HeaderNameLength * sizeof(CHAR);
  806. pUserCurrentUnknownHeader->pName =
  807. FIXUP_PTR(
  808. PSTR,
  809. pUserBuffer,
  810. pKernelBuffer,
  811. pCurrentBufferPtr,
  812. BufferLength
  813. );
  814. RtlCopyMemory(
  815. pCurrentBufferPtr,
  816. pUnknownHeader->pHeaderName,
  817. pUnknownHeader->HeaderNameLength
  818. );
  819. pCurrentBufferPtr += pUnknownHeader->HeaderNameLength;
  820. //
  821. // terminate it
  822. //
  823. ((PSTR)pCurrentBufferPtr)[0] = ANSI_NULL;
  824. pCurrentBufferPtr += sizeof(CHAR);
  825. //
  826. // Now copy in the header value.
  827. //
  828. ASSERT(pUnknownHeader->HeaderValue.HeaderLength <= 0x7fff);
  829. if (pUnknownHeader->HeaderValue.HeaderLength == 0)
  830. {
  831. pUserCurrentUnknownHeader->RawValueLength = 0;
  832. pUserCurrentUnknownHeader->pRawValue = NULL;
  833. }
  834. else
  835. {
  836. pUserCurrentUnknownHeader->RawValueLength =
  837. (USHORT)(pUnknownHeader->HeaderValue.HeaderLength * sizeof(CHAR));
  838. pUserCurrentUnknownHeader->pRawValue =
  839. FIXUP_PTR(
  840. PSTR,
  841. pUserBuffer,
  842. pKernelBuffer,
  843. pCurrentBufferPtr,
  844. BufferLength
  845. );
  846. RtlCopyMemory(
  847. pCurrentBufferPtr,
  848. pUnknownHeader->HeaderValue.pHeader,
  849. pUnknownHeader->HeaderValue.HeaderLength
  850. );
  851. pCurrentBufferPtr += pUnknownHeader->HeaderValue.HeaderLength;
  852. //
  853. // terminate it
  854. //
  855. ((PSTR)pCurrentBufferPtr)[0] = ANSI_NULL;
  856. pCurrentBufferPtr += sizeof(CHAR);
  857. }
  858. //
  859. // skip to the next header
  860. //
  861. pUserCurrentUnknownHeader++;
  862. //
  863. // Free the unknown header structure now, as well as the pointer
  864. // (if needed).
  865. //
  866. if (pUnknownHeader->HeaderValue.OurBuffer == 1)
  867. {
  868. UL_FREE_POOL(
  869. pUnknownHeader->HeaderValue.pHeader,
  870. UL_KNOWN_HEADER_POOL_TAG
  871. );
  872. pUnknownHeader->HeaderValue.OurBuffer = 0;
  873. }
  874. UL_FREE_POOL( pUnknownHeader, UL_UNKNOWN_HEADER_POOL_TAG );
  875. }
  876. //
  877. // no more unknown headers exist
  878. //
  879. pRequest->UnknownHeaderCount = 0;
  880. //
  881. // Make sure we didn't use too much
  882. //
  883. ASSERT(DIFF(pCurrentBufferPtr - pKernelBuffer) <= BufferLength);
  884. return STATUS_SUCCESS;
  885. }