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.

696 lines
19 KiB

  1. /*++
  2. Copyright (c) 1994 Microsoft Corporation
  3. Module Name:
  4. sendapi.cxx
  5. Abstract:
  6. This file contains the implementation of the HttpSendRequestA API.
  7. Contents:
  8. WinHttpSendRequest
  9. HttpSendRequestA
  10. WinHttpReceiveResponse
  11. HttpWrapSendRequest
  12. Author:
  13. Keith Moore (keithmo) 16-Nov-1994
  14. Revision History:
  15. 29-Apr-97 rfirth
  16. Conversion to FSM
  17. --*/
  18. #include <wininetp.h>
  19. #include <perfdiag.hxx>
  20. //
  21. // private prototypes
  22. //
  23. PRIVATE
  24. BOOL
  25. HttpWrapSendRequest(
  26. IN HINTERNET hRequest,
  27. IN LPCSTR lpszHeaders OPTIONAL,
  28. IN DWORD dwHeadersLength,
  29. IN LPVOID lpOptional OPTIONAL,
  30. IN DWORD dwOptionalLength,
  31. IN DWORD dwOptionalLengthTotal,
  32. IN AR_TYPE arRequest,
  33. OUT HTTP_REQUEST_HANDLE_OBJECT** pHandleToDeref,
  34. IN DWORD_PTR dwContext=NULL
  35. );
  36. //
  37. // functions
  38. //
  39. INTERNETAPI
  40. BOOL
  41. WINAPI
  42. HttpSendRequestA(
  43. IN HINTERNET hRequest,
  44. IN LPCSTR lpszHeaders OPTIONAL,
  45. IN DWORD dwHeadersLength,
  46. IN LPVOID lpOptional OPTIONAL,
  47. IN DWORD dwOptionalLength
  48. )
  49. /*++
  50. Routine Description:
  51. Sends the specified request to the HTTP server.
  52. Arguments:
  53. hRequest - An open HTTP request handle returned by
  54. HttpOpenRequest()
  55. lpszHeaders - Additional headers to be appended to the request.
  56. This may be NULL if there are no additional
  57. headers to append
  58. dwHeadersLength - The length (in characters) of the additional
  59. headers. If this is -1L and lpszAdditional is
  60. non-NULL, then lpszAdditional is assumed to be
  61. zero terminated (ASCIIZ)
  62. lpOptionalData - Any optional data to send immediately after the
  63. request headers. This is typically used for POST
  64. operations. This may be NULL if there is no
  65. optional data to send
  66. dwOptionalDataLength - The length (in BYTEs) of the optional data. This
  67. may be zero if there is no optional data to send
  68. Return Value:
  69. BOOL
  70. Success - TRUE
  71. Failure - FALSE. For more information call GetLastError(). If the
  72. request was async, then GetLastError() will return
  73. ERROR_IO_PENDING which means that the operation initially
  74. succeeded, and that the caller should wait for the status
  75. callback to discover the final success/failure status
  76. --*/
  77. {
  78. DEBUG_ENTER((DBG_API,
  79. Bool,
  80. "HttpSendRequestA",
  81. "%#x, %.80q, %d, %#x, %d",
  82. hRequest,
  83. lpszHeaders,
  84. dwHeadersLength,
  85. lpOptional,
  86. dwOptionalLength
  87. ));
  88. BOOL fRet= HttpWrapSendRequest(
  89. hRequest,
  90. lpszHeaders,
  91. dwHeadersLength,
  92. lpOptional,
  93. dwOptionalLength,
  94. 0,
  95. AR_HTTP_SEND_REQUEST,
  96. NULL
  97. );
  98. DEBUG_LEAVE(fRet);
  99. return fRet;
  100. }
  101. INTERNETAPI
  102. BOOL
  103. WINAPI
  104. WinHttpSendRequest(
  105. IN HINTERNET hRequest,
  106. IN LPCWSTR lpszHeaders OPTIONAL,
  107. IN DWORD dwHeadersLength,
  108. IN LPVOID lpOptional OPTIONAL,
  109. IN DWORD dwOptionalLength,
  110. IN DWORD dwTotalLength,
  111. IN DWORD_PTR dwContext
  112. )
  113. /*++
  114. Routine Description:
  115. Sends the specified request to the HTTP server.
  116. Arguments:
  117. hRequest - An open HTTP request handle returned by
  118. HttpOpenRequest()
  119. lpszHeaders - Additional headers to be appended to the request.
  120. This may be NULL if there are no additional
  121. headers to append
  122. dwHeadersLength - The length (in characters) of the additional
  123. headers. If this is -1L and lpszAdditional is
  124. non-NULL, then lpszAdditional is assumed to be
  125. zero terminated (ASCIIZ)
  126. lpOptionalData - Any optional data to send immediately after the
  127. request headers. This is typically used for POST
  128. operations. This may be NULL if there is no
  129. optional data to send
  130. dwOptionalDataLength - The length (in BYTEs) of the optional data. This
  131. may be zero if there is no optional data to send
  132. Return Value:
  133. BOOL
  134. Success - TRUE
  135. Failure - FALSE. For more information call GetLastError(). If the
  136. request was async, then GetLastError() will return
  137. ERROR_IO_PENDING which means that the operation initially
  138. succeeded, and that the caller should wait for the status
  139. callback to discover the final success/failure status
  140. --*/
  141. {
  142. DEBUG_ENTER2_API((DBG_API,
  143. Bool,
  144. "WinHttpSendRequest",
  145. "%#x, %.80wq, %d, %#x, %d, %d, %x",
  146. hRequest,
  147. lpszHeaders,
  148. dwHeadersLength,
  149. lpOptional,
  150. dwOptionalLength,
  151. dwTotalLength,
  152. dwContext
  153. ));
  154. TRACE_ENTER2_API((DBG_API,
  155. Bool,
  156. "WinHttpSendRequest",
  157. hRequest,
  158. "%#x, %.80wq, %d, %#x, %d, %d, %x",
  159. hRequest,
  160. !lpszHeaders || IsBadReadPtr(lpszHeaders, 1)? L"": lpszHeaders,
  161. dwHeadersLength,
  162. lpOptional,
  163. dwOptionalLength,
  164. dwTotalLength,
  165. dwContext
  166. ));
  167. DWORD dwErr = ERROR_SUCCESS;
  168. BOOL fResult = FALSE;
  169. MEMORYPACKET mpHeaders;
  170. if (!hRequest)
  171. {
  172. dwErr = ERROR_INVALID_HANDLE;
  173. goto cleanup;
  174. }
  175. if (lpszHeaders && IsBadReadPtr(lpszHeaders, 1))
  176. {
  177. dwErr = ERROR_INVALID_PARAMETER;
  178. goto cleanup;
  179. }
  180. if (dwHeadersLength == -1L)
  181. {
  182. dwHeadersLength = lpszHeaders ? lstrlenW(lpszHeaders) : 0;
  183. }
  184. if (lpszHeaders)
  185. {
  186. if ((dwHeadersLength == -1)
  187. ? IsBadStringPtrW(lpszHeaders, (UINT_PTR)-1)
  188. : IsBadReadPtr(lpszHeaders, dwHeadersLength))
  189. {
  190. dwErr = ERROR_INVALID_PARAMETER;
  191. goto cleanup;
  192. }
  193. ALLOC_MB(lpszHeaders, dwHeadersLength, mpHeaders);
  194. if (!mpHeaders.psStr)
  195. {
  196. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  197. goto cleanup;
  198. }
  199. UNICODE_TO_ANSI(lpszHeaders, mpHeaders);
  200. }
  201. if (lpOptional
  202. && dwOptionalLength
  203. && IsBadReadPtr(lpOptional, dwOptionalLength) )
  204. {
  205. dwErr = ERROR_INVALID_PARAMETER;
  206. goto cleanup;
  207. }
  208. AR_TYPE ar;
  209. // Always require a WinHttpReceiveResponse to initiate
  210. // FSM_STATE_4 onwards in HTTP_REQUEST_HANDLE_OBJECT::HttpSendRequest_Start:
  211. if (dwOptionalLength <= dwTotalLength)
  212. {
  213. ar = AR_HTTP_BEGIN_SEND_REQUEST;
  214. }
  215. else
  216. {
  217. dwErr = ERROR_INVALID_PARAMETER;
  218. goto cleanup;
  219. }
  220. HTTP_REQUEST_HANDLE_OBJECT* pRequest = NULL;
  221. fResult = HttpWrapSendRequest(hRequest, mpHeaders.psStr, mpHeaders.dwSize,
  222. lpOptional, dwOptionalLength, dwTotalLength, ar, &pRequest, dwContext);
  223. // This calls SetLastError if fResult is FALSE.
  224. if (fResult)
  225. {
  226. if (pRequest)
  227. {
  228. InternetIndicateStatus(WINHTTP_CALLBACK_STATUS_SENDREQUEST_COMPLETE,
  229. NULL,
  230. NULL
  231. );
  232. // So that we have a refcount on the object going into the callback.
  233. DereferenceObject((LPVOID)pRequest);
  234. }
  235. }
  236. else if ((dwErr = GetLastError()) == ERROR_IO_PENDING)
  237. {
  238. SetLastError(dwErr = ERROR_SUCCESS);
  239. fResult = TRUE;
  240. }
  241. cleanup:
  242. if (dwErr!=ERROR_SUCCESS)
  243. {
  244. DEBUG_ERROR(HTTP, dwErr);
  245. SetLastError(dwErr);
  246. }
  247. DEBUG_LEAVE_API(fResult);
  248. return fResult;
  249. }
  250. INTERNETAPI
  251. BOOL
  252. WINAPI
  253. WinHttpReceiveResponse(
  254. IN HINTERNET hRequest,
  255. IN LPVOID lpBuffersOut OPTIONAL
  256. )
  257. /*++
  258. Routine Description:
  259. description-of-function.
  260. Arguments:
  261. hRequest -
  262. lpBuffersOut -
  263. dwFlags -
  264. dwContext -
  265. Return Value:
  266. BOOL
  267. --*/
  268. {
  269. DEBUG_ENTER_API((DBG_API,
  270. Bool,
  271. "WinHttpReceiveResponse",
  272. "%#x, %#x",
  273. hRequest,
  274. lpBuffersOut
  275. ));
  276. DWORD dwErr = ERROR_SUCCESS;
  277. BOOL fResult = FALSE;
  278. if (!hRequest)
  279. {
  280. dwErr = ERROR_INVALID_HANDLE;
  281. }
  282. else if (lpBuffersOut)
  283. {
  284. dwErr = ERROR_INVALID_PARAMETER;
  285. }
  286. else
  287. {
  288. HTTP_REQUEST_HANDLE_OBJECT* pRequest = NULL;
  289. fResult = HttpWrapSendRequest(hRequest, NULL, 0, NULL, 0, 0, AR_HTTP_END_SEND_REQUEST, &pRequest);
  290. if (fResult)
  291. {
  292. if (pRequest)
  293. {
  294. InternetIndicateStatus(WINHTTP_CALLBACK_STATUS_HEADERS_AVAILABLE,
  295. NULL,
  296. NULL
  297. );
  298. // So that we have a refcount on the object going into the callback.
  299. DereferenceObject((LPVOID)pRequest);
  300. }
  301. }
  302. else if ((dwErr = GetLastError()) == ERROR_IO_PENDING)
  303. {
  304. SetLastError(dwErr = ERROR_SUCCESS);
  305. fResult = TRUE;
  306. }
  307. }
  308. if (dwErr!=ERROR_SUCCESS)
  309. {
  310. DEBUG_ERROR(HTTP, dwErr);
  311. SetLastError(dwErr);
  312. }
  313. DEBUG_LEAVE_API(fResult);
  314. return fResult;
  315. }
  316. PRIVATE
  317. BOOL
  318. HttpWrapSendRequest(
  319. IN HINTERNET hRequest,
  320. IN LPCSTR lpszHeaders OPTIONAL,
  321. IN DWORD dwHeadersLength,
  322. IN LPVOID lpOptional OPTIONAL,
  323. IN DWORD dwOptionalLength,
  324. IN DWORD dwOptionalLengthTotal,
  325. IN AR_TYPE arRequest,
  326. OUT HTTP_REQUEST_HANDLE_OBJECT** pHandleToDeref,
  327. IN DWORD_PTR dwContext
  328. )
  329. /*++
  330. Routine Description:
  331. Sends the specified request to the HTTP server.
  332. Arguments:
  333. hRequest - An open HTTP request handle returned by
  334. HttpOpenRequest()
  335. lpszHeaders - Additional headers to be appended to the request.
  336. This may be NULL if there are no additional
  337. headers to append
  338. dwHeadersLength - The length (in characters) of the additional
  339. headers. If this is -1L and lpszAdditional is
  340. non-NULL, then lpszAdditional is assumed to be
  341. zero terminated (ASCIIZ)
  342. lpOptionalData - Any optional data to send immediately after the
  343. request headers. This is typically used for POST
  344. operations. This may be NULL if there is no
  345. optional data to send
  346. dwOptionalDataLength - The length (in BYTEs) of the optional data. This
  347. may be zero if there is no optional data to send
  348. dwOptionalLengthTotal - Total length need to be sent for File Upload.
  349. arRequest - Which API the caller is making,
  350. assumed to be HttpEndRequestA, HttpSendRequestExA, or
  351. HttpSendRequestA
  352. Return Value:
  353. BOOL
  354. Success - TRUE
  355. Failure - FALSE. For more information call GetLastError(). If the
  356. request was async, then GetLastError() will return
  357. ERROR_IO_PENDING which means that the operation initially
  358. succeeded, and that the caller should wait for the status
  359. callback to discover the final success/failure status
  360. Comments:
  361. --*/
  362. {
  363. DEBUG_ENTER((DBG_HTTP,
  364. Bool,
  365. "HttpWrapSendRequest",
  366. "%#x, %.80q, %d, %#x, %d, %d, %x",
  367. hRequest,
  368. lpszHeaders,
  369. dwHeadersLength,
  370. lpOptional,
  371. dwOptionalLength,
  372. dwOptionalLengthTotal,
  373. dwContext
  374. ));
  375. PERF_ENTER(HttpWrapSendRequest);
  376. DWORD error = ERROR_SUCCESS;
  377. HINTERNET hRequestMapped = NULL;
  378. BOOL bDeref = TRUE;
  379. BOOL isLocal;
  380. BOOL isAsync = FALSE;
  381. if (!GlobalDataInitialized) {
  382. error = ERROR_WINHTTP_NOT_INITIALIZED;
  383. goto done;
  384. }
  385. //
  386. // we will need the thread info for several items
  387. //
  388. LPINTERNET_THREAD_INFO lpThreadInfo;
  389. lpThreadInfo = InternetGetThreadInfo();
  390. if (lpThreadInfo == NULL) {
  391. error = ERROR_WINHTTP_INTERNAL_ERROR;
  392. goto done;
  393. }
  394. //
  395. // the only FSMs that can come before this one are InternetOpenUrl() or
  396. // HttpSendRequest() when we are performing nested send for https://
  397. // tunnelling through proxy
  398. //
  399. INET_ASSERT((lpThreadInfo->Fsm == NULL)
  400. || (lpThreadInfo->Fsm->GetType() == FSM_TYPE_PARSE_HTTP_URL)
  401. || (lpThreadInfo->Fsm->GetType() == FSM_TYPE_OPEN_PROXY_TUNNEL)
  402. );
  403. INET_ASSERT( arRequest == AR_HTTP_SEND_REQUEST ||
  404. arRequest == AR_HTTP_BEGIN_SEND_REQUEST ||
  405. arRequest == AR_HTTP_END_SEND_REQUEST );
  406. //
  407. // map the handle
  408. //
  409. error = MapHandleToAddress(hRequest, (LPVOID *)&hRequestMapped, FALSE);
  410. if ((error != ERROR_SUCCESS) && (hRequestMapped == NULL)) {
  411. goto quit;
  412. }
  413. //
  414. // Cast it to the object that we know. We are going to do caching
  415. // semantics with this
  416. //
  417. HTTP_REQUEST_HANDLE_OBJECT * pRequest;
  418. pRequest = (HTTP_REQUEST_HANDLE_OBJECT *)hRequestMapped;
  419. //
  420. // set the context and handle info & reset the error variables,
  421. // but only if not for a ReceiveResponse call.
  422. //
  423. if (arRequest != AR_HTTP_END_SEND_REQUEST)
  424. {
  425. if (dwContext)
  426. pRequest->SetContext(dwContext);
  427. // We need this information to special-case for Redirects and Auth because of RR FSM changes:
  428. pRequest->SetWriteRequired(dwOptionalLength < dwOptionalLengthTotal);
  429. }
  430. //
  431. // For a call to WinHttpSendRequest (arRequst == AR_HTTP_BEGIN_SEND_REQUEST), SetProxyTunnelingSuppressWrite()
  432. //will be called again setting the value to TRUE iff we really are trying to tunnel through a proxy.
  433. // For a call to WinHttpReceiveResponse (arRequest == AR_HTTP_END_SEND_REQUEST), WinHttpWriteData is no longer
  434. //valid to be called, and so writes are suppressed by the request state. Its appropriate to call
  435. //SetProxyTunnelingSuppressWrite(FALSE) in this case to ensure the request's state logic kicks in
  436. //for denying the request though.
  437. //
  438. pRequest->SetProxyTunnelingSuppressWrite(FALSE);
  439. _InternetSetObjectHandle(lpThreadInfo, hRequest, hRequestMapped);
  440. _InternetClearLastError(lpThreadInfo);
  441. //
  442. // quit now if the handle was invalid
  443. //
  444. if (error != ERROR_SUCCESS) {
  445. goto quit;
  446. }
  447. //
  448. // use RIsHandleLocal() to discover 4 things:
  449. //
  450. // 1. Handle is valid
  451. // 2. Handle is of expected type (HTTP Request in this case)
  452. // 3. Handle is local or remote
  453. // 4. Handle supports async I/O
  454. //
  455. error = RIsHandleLocal(hRequestMapped,
  456. &isLocal,
  457. &isAsync,
  458. TypeHttpRequestHandle
  459. );
  460. if (error != ERROR_SUCCESS) {
  461. goto quit;
  462. }
  463. if (isAsync)
  464. {
  465. error = InitializeAsyncSupport();
  466. if (error != ERROR_SUCCESS)
  467. {
  468. goto quit;
  469. }
  470. }
  471. //
  472. // For SEND_REQUEST, and BEGIN_SEND_REQUEST, we need
  473. // to do some basic initalization
  474. //
  475. if ( arRequest == AR_HTTP_SEND_REQUEST ||
  476. arRequest == AR_HTTP_BEGIN_SEND_REQUEST)
  477. {
  478. error = pRequest->InitBeginSendRequest(lpszHeaders,
  479. dwHeadersLength,
  480. &lpOptional,
  481. &dwOptionalLength,
  482. dwOptionalLengthTotal
  483. );
  484. if ( error != ERROR_SUCCESS)
  485. {
  486. goto quit;
  487. }
  488. // (Re)set flag to indicate WinHttpReceiveResponse needs to be called.
  489. pRequest->SetReceiveResponseState(FALSE);
  490. // RENO 35599: If sending a new request, ensure the OptionalSaved member
  491. // variables are cleared out.
  492. pRequest->ClearSavedOptionalData();
  493. }
  494. else if (arRequest == AR_HTTP_END_SEND_REQUEST)
  495. {
  496. pRequest->SetReceiveResponseState(TRUE);
  497. }
  498. //
  499. // send the request to the server. This may involve redirections and user
  500. // authentication
  501. //
  502. //error = DoFsm(New CFsm_HttpSendRequest(lpOptional, dwOptionalLength, pRequest, arRequest));
  503. //if (error == ERROR_IO_PENDING) {
  504. // bDeref = FALSE;
  505. //}
  506. CFsm_HttpSendRequest * pFsm;
  507. pFsm = New CFsm_HttpSendRequest(lpOptional, dwOptionalLength, pRequest, arRequest);
  508. if (pFsm != NULL)
  509. {
  510. if (isAsync && !lpThreadInfo->IsAsyncWorkerThread)
  511. {
  512. error = StartFsmChain(pFsm, pRequest, TRUE, TRUE);
  513. if ((error == ERROR_SUCCESS)
  514. && pHandleToDeref)
  515. {
  516. // Deref in the outer api call for sync success in async case.
  517. *pHandleToDeref = pRequest;
  518. bDeref = FALSE;
  519. }
  520. }
  521. else
  522. {
  523. error = StartFsmChain(pFsm, pRequest, FALSE, FALSE);
  524. }
  525. if (error == ERROR_IO_PENDING)
  526. {
  527. bDeref = FALSE;
  528. }
  529. }
  530. else
  531. {
  532. error = ERROR_NOT_ENOUGH_MEMORY;
  533. }
  534. quit:
  535. //
  536. // if we went async don't deref the handle
  537. //
  538. if (bDeref && (hRequestMapped != NULL)) {
  539. DereferenceObject((LPVOID)hRequestMapped);
  540. }
  541. done:
  542. BOOL success = TRUE;
  543. // SetLastError must be called after PERF_LEAVE !!!
  544. PERF_LEAVE(HttpWrapSendRequest);
  545. if (error != ERROR_SUCCESS)
  546. {
  547. DEBUG_ERROR(HTTP, error);
  548. SetLastError(error);
  549. success = FALSE;
  550. }
  551. DEBUG_LEAVE(success);
  552. return success;
  553. }