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.

547 lines
14 KiB

  1. /*++
  2. Copyright (c) 1994 Microsoft Corporation
  3. Module Name:
  4. add.cxx
  5. Abstract:
  6. This file contains the implementation of the HttpAddRequestHeadersA API.
  7. The following functions are exported by this module:
  8. HttpAddRequestHeadersA
  9. WinHttpAddRequestHeaders
  10. Author:
  11. Keith Moore (keithmo) 16-Nov-1994
  12. Revision History:
  13. Modified to make HttpAddRequestHeadersA remotable. madana (2/8/95)
  14. --*/
  15. #include <wininetp.h>
  16. #include "httpp.h"
  17. //
  18. // private manifests
  19. //
  20. #define VALID_ADD_FLAGS (HTTP_ADDREQ_FLAG_ADD_IF_NEW \
  21. | HTTP_ADDREQ_FLAG_ADD \
  22. | HTTP_ADDREQ_FLAG_COALESCE_WITH_COMMA \
  23. | HTTP_ADDREQ_FLAG_REPLACE \
  24. | HTTP_ADDREQ_FLAG_COALESCE_WITH_SEMICOLON \
  25. )
  26. //
  27. // functions
  28. //
  29. INTERNETAPI
  30. BOOL
  31. WINAPI
  32. HttpAddRequestHeadersA(
  33. IN HINTERNET hRequest,
  34. IN LPCSTR lpszHeaders,
  35. IN DWORD dwHeadersLength,
  36. IN DWORD dwModifiers
  37. )
  38. /*++
  39. Routine Description:
  40. Appends additional header(s) to an HTTP request handle
  41. Arguments:
  42. hRequest - An open HTTP request handle returned by HttpOpenRequest()
  43. lpszHeaders - The headers to append to the request. Each header must be
  44. terminated by a CR/LF pair.
  45. dwHeadersLength - The length (in characters) of the headers. If this is -1L
  46. then lpszHeaders is assumed to be zero terminated (ASCIIZ)
  47. dwModifiers - flags controlling operation. Can be one or more of:
  48. HTTP_ADDREQ_FLAG_ADD_IF_NEW
  49. - add the header, but only if it does not already
  50. exist. Index must be zero
  51. HTTP_ADDREQ_FLAG_ADD
  52. - if HTTP_ADDREQ_FLAG_REPLACE is set, but the header
  53. is not found and this flag is set then the header
  54. is added, so long as there is a valid header-value
  55. HTTP_ADDREQ_FLAG_COALESCE
  56. HTTP_ADDREQ_FLAG_COALESCE_WITH_SEMICOLON
  57. HTTP_ADDREQ_FLAG_COALESCE_WITH_COMMA
  58. - concatenate headers of same name. E.g. if we
  59. already have "Accept: text/html" then adding
  60. "Accept: text/*" will create
  61. "Accept: text/html, text/*"
  62. HTTP_ADDREQ_FLAG_REPLACE
  63. - replaces the named header. Only one header can be
  64. supplied. If header-value is empty then the header
  65. is removed
  66. Return Value:
  67. Success - TRUE
  68. The header was appended successfully
  69. Failure - FALSE
  70. The operation failed. Error status is available by calling
  71. GetLastError()
  72. --*/
  73. {
  74. DEBUG_ENTER_API((DBG_API,
  75. Bool,
  76. "HttpAddRequestHeadersA",
  77. "%#x, %.80q, %d, %#x",
  78. hRequest,
  79. lpszHeaders,
  80. dwHeadersLength,
  81. dwModifiers
  82. ));
  83. DWORD error;
  84. HINTERNET hRequestMapped = NULL;
  85. DWORD nestingLevel = 0;
  86. if (!GlobalDataInitialized) {
  87. error = ERROR_WINHTTP_NOT_INITIALIZED;
  88. goto done;
  89. }
  90. //
  91. // get the thread info
  92. //
  93. LPINTERNET_THREAD_INFO lpThreadInfo;
  94. lpThreadInfo = InternetGetThreadInfo();
  95. if (lpThreadInfo == NULL) {
  96. error = ERROR_WINHTTP_INTERNAL_ERROR;
  97. goto done;
  98. }
  99. //
  100. // map the handle
  101. //
  102. error = MapHandleToAddress(hRequest, (LPVOID *)&hRequestMapped, FALSE);
  103. if (error != ERROR_SUCCESS) {
  104. goto quit;
  105. }
  106. _InternetIncNestingCount();
  107. nestingLevel = 1;
  108. //
  109. // validate handle
  110. //
  111. BOOL isLocal;
  112. BOOL isAsync;
  113. error = RIsHandleLocal(hRequestMapped,
  114. &isLocal,
  115. &isAsync,
  116. TypeHttpRequestHandle
  117. );
  118. if (error != ERROR_SUCCESS) {
  119. goto quit;
  120. }
  121. //
  122. // validate parameters
  123. //
  124. INET_ASSERT(!(
  125. (lpszHeaders == NULL)
  126. || (*lpszHeaders == '\0')
  127. || (dwHeadersLength == 0)
  128. || (dwModifiers & (HTTP_ADDREQ_FLAGS_MASK & ~VALID_ADD_FLAGS))) );
  129. INET_ASSERT(error == ERROR_SUCCESS);
  130. //
  131. // BUGBUG - we should determine whether the app is trying to give us a bogus
  132. // header, and whether the header conforms to the format:
  133. //
  134. // "<header>[:[ <value>]]"
  135. //
  136. if (dwHeadersLength == (DWORD)-1)
  137. {
  138. dwHeadersLength = (DWORD)lstrlen(lpszHeaders);
  139. }
  140. if (error == ERROR_SUCCESS) {
  141. error = wHttpAddRequestHeaders(hRequestMapped,
  142. lpszHeaders,
  143. dwHeadersLength,
  144. dwModifiers
  145. );
  146. }
  147. quit:
  148. _InternetDecNestingCount(nestingLevel);
  149. done:
  150. if (error != ERROR_SUCCESS) {
  151. DEBUG_ERROR(HTTP, error);
  152. SetLastError(error);
  153. }
  154. if (hRequestMapped != NULL) {
  155. DereferenceObject((LPVOID)hRequestMapped);
  156. }
  157. DEBUG_LEAVE_API(error == ERROR_SUCCESS);
  158. return error == ERROR_SUCCESS;
  159. }
  160. INTERNETAPI
  161. BOOL
  162. WINAPI
  163. WinHttpAddRequestHeaders(
  164. IN HINTERNET hRequest,
  165. IN LPCWSTR lpszHeaders,
  166. IN DWORD dwHeadersLength,
  167. IN DWORD dwModifiers
  168. )
  169. /*++
  170. Routine Description:
  171. Appends additional header(s) to an HTTP request handle.
  172. Arguments:
  173. hHttpRequest - An open HTTP request handle returned by HttpOpenRequest().
  174. lpszHeaders - The headers to append to the request. Each header must be
  175. terminated by a CR/LF pair.
  176. dwHeadersLength - The length (in characters) of the headers. If this is
  177. -1L, then lpszHeaders is assumed to be zero terminated (ASCIIZ).
  178. dwModifiers -
  179. Return Value:
  180. TRUE - The header was appended successfully.
  181. FALSE - The operation failed. Error status is available by calling
  182. GetLastError().
  183. Comments:
  184. --*/
  185. {
  186. DEBUG_ENTER_API((DBG_API,
  187. Bool,
  188. "WinHttpAddRequestHeaders",
  189. "%#x, %.80wq, %d, %#x",
  190. hRequest,
  191. lpszHeaders,
  192. dwHeadersLength,
  193. dwModifiers
  194. ));
  195. DWORD dwErr = ERROR_SUCCESS;
  196. BOOL fResult = FALSE;
  197. if (!lpszHeaders
  198. || *lpszHeaders==L'\0'
  199. || !dwHeadersLength
  200. || ((dwHeadersLength == -1)
  201. ? IsBadStringPtrW(lpszHeaders, -1)
  202. : IsBadReadPtr(lpszHeaders, dwHeadersLength))
  203. || (dwModifiers & (HTTP_ADDREQ_FLAGS_MASK & ~VALID_ADD_FLAGS)))
  204. {
  205. dwErr = ERROR_INVALID_PARAMETER;
  206. }
  207. else
  208. {
  209. MEMORYPACKET mpHeaders;
  210. ALLOC_MB(lpszHeaders, (dwHeadersLength==-1L ? 0 : dwHeadersLength), mpHeaders);
  211. if (mpHeaders.psStr)
  212. {
  213. UNICODE_TO_ANSI(lpszHeaders, mpHeaders);
  214. fResult = HttpAddRequestHeadersA(hRequest, mpHeaders.psStr, mpHeaders.dwSize, dwModifiers);
  215. }
  216. else
  217. {
  218. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  219. }
  220. }
  221. if (dwErr!=ERROR_SUCCESS)
  222. {
  223. SetLastError(dwErr);
  224. DEBUG_ERROR(HTTP, dwErr);
  225. }
  226. DEBUG_LEAVE_API(fResult);
  227. return fResult;
  228. }
  229. PUBLIC
  230. DWORD
  231. wHttpAddRequestHeaders(
  232. IN HINTERNET hRequest,
  233. IN LPCSTR lpszHeaders,
  234. IN DWORD dwHeadersLength,
  235. IN DWORD dwModifiers
  236. )
  237. /*++
  238. Routine Description:
  239. Worker function to append additional header(s) to an HTTP request handle
  240. Arguents:
  241. hRequest - handle of HTTP request
  242. lpszHeaders - pointer to buffer containing one or more headers
  243. dwHeadersLength - length of lpszHeaders. Cannot be -1 at this stage
  244. dwModifiers - flags controlling operation
  245. Return Value:
  246. DWORD
  247. Success - ERROR_SUCCESS
  248. Failure - ERROR_INVALID_PARAMETER
  249. The header string(s) was bad after all
  250. ERROR_WINHTTP_INCORRECT_HANDLE_STATE
  251. We can't add headers to this object at this time
  252. ERROR_HTTP_HEADER_NOT_FOUND
  253. We were asked to replace a header, but couldn't find it
  254. ERROR_HTTP_HEADER_ALREADY_EXISTS
  255. We were asked to add a header, only if one of the same name
  256. doesn't already exist. It does
  257. --*/
  258. {
  259. //
  260. // dwHeadersLength cannot be -1 or 0 at this stage. Nor can lpszHeaders be
  261. // NULL
  262. //
  263. INET_ASSERT(lpszHeaders != NULL);
  264. INET_ASSERT(dwHeadersLength != (DWORD)-1);
  265. INET_ASSERT(dwHeadersLength != 0);
  266. DEBUG_ENTER((DBG_HTTP,
  267. Dword,
  268. "wHttpAddRequestHeaders",
  269. "%#x, %#x [%.80q], %d, %#x",
  270. hRequest,
  271. lpszHeaders,
  272. lpszHeaders,
  273. dwHeadersLength,
  274. dwModifiers
  275. ));
  276. //
  277. // get the underlying object and check that we can add headers
  278. //
  279. HTTP_REQUEST_HANDLE_OBJECT * pRequest;
  280. pRequest = (HTTP_REQUEST_HANDLE_OBJECT *)hRequest;
  281. DWORD error;
  282. if (!IS_VALID_HTTP_STATE(pRequest, ADD, TRUE)) {
  283. error = ERROR_WINHTTP_INCORRECT_HANDLE_STATE;
  284. goto quit;
  285. }
  286. DWORD offset;
  287. LPSTR header;
  288. offset = 0;
  289. header = (LPSTR)lpszHeaders;
  290. do {
  291. //
  292. // first time: ignore any empty strings; subsequent time: clean off any
  293. // trailing line termination
  294. //
  295. while ((offset < dwHeadersLength)
  296. && ((lpszHeaders[offset] == '\r') || (lpszHeaders[offset] == '\n'))) {
  297. ++offset;
  298. }
  299. if (offset == dwHeadersLength) {
  300. //
  301. // even if app tried adding empty line(s), we return success
  302. //
  303. error = ERROR_SUCCESS;
  304. break;
  305. }
  306. DWORD length;
  307. DWORD nameLength;
  308. DWORD valueLength;
  309. LPSTR value;
  310. BOOL done;
  311. nameLength = 0;
  312. valueLength = 0;
  313. value = NULL;
  314. //
  315. // break the header into header-name, header-value pairs. Exclude CR-LF
  316. // from the header-value (if present)
  317. //
  318. for (length = 0, header = (LPSTR)&lpszHeaders[offset];
  319. offset < dwHeadersLength;
  320. ++length, ++offset) {
  321. char ch = header[length];
  322. if ((ch == '\r') || (ch == '\n')) {
  323. //
  324. // end of this particular header
  325. //
  326. break;
  327. } else if (ch == ':') {
  328. if (nameLength == 0) {
  329. //
  330. // found end of header name
  331. //
  332. nameLength = length;
  333. value = &header[length];
  334. }
  335. }
  336. }
  337. if (length == 0) {
  338. //
  339. // empty string
  340. //
  341. continue;
  342. } else if (nameLength == 0) {
  343. //
  344. // entry consists of just header-name (e.g. "Accept[\r\n]")
  345. //
  346. nameLength = length;
  347. } else {
  348. //
  349. // find the start of the header-value
  350. //
  351. valueLength = (DWORD) (header + length - value);
  352. //
  353. // N.B. We are allowing any mixture of ':' and ' ' between header
  354. // name and value, but this is probably not a big deal...
  355. //
  356. while ((*value == ':') || (*value == ' ') && (valueLength != 0)) {
  357. ++value;
  358. --valueLength;
  359. }
  360. }
  361. if (dwModifiers
  362. & (HTTP_ADDREQ_FLAG_REPLACE | HTTP_ADDREQ_FLAG_ADD_IF_NEW)) {
  363. //
  364. // replace or remove the header
  365. //
  366. error = pRequest->ReplaceRequestHeader(
  367. header,
  368. nameLength,
  369. value,
  370. valueLength,
  371. dwModifiers & HTTP_ADDREQ_INDEX_MASK,
  372. dwModifiers & HTTP_ADDREQ_FLAGS_MASK
  373. );
  374. } else if (valueLength != 0) {
  375. //
  376. // add a single, unterminated header string to the request headers.
  377. // Since these headers came from the app, we don't trust it to get
  378. // the header termination right (number & type of line terminators)
  379. // so we add it ourselves
  380. //
  381. error = pRequest->AddRequestHeader(
  382. header,
  383. nameLength,
  384. value,
  385. valueLength,
  386. dwModifiers & HTTP_ADDREQ_INDEX_MASK,
  387. dwModifiers & HTTP_ADDREQ_FLAGS_MASK
  388. );
  389. } else {
  390. //
  391. // BUGBUG - we are adding headers, but the header-value is not
  392. // present. This is a somewhat tricky situation because we
  393. // we may have already added some headers, resulting in
  394. // the app not really knowing which headers were good and
  395. // which failed; additionally, one or more of the headers
  396. // may have been added, increasing the apps confusion. The
  397. // best way to handle this (if necessary) is to check the
  398. // header name/value pairs w.r.t. the dwModifiers flags.
  399. // HOWEVER, even then we can get into a state down here
  400. // where we add a couple of headers, then fail...
  401. //
  402. error = ERROR_INVALID_PARAMETER;
  403. }
  404. } while (error == ERROR_SUCCESS);
  405. quit:
  406. DEBUG_LEAVE(error);
  407. return error;
  408. }