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.

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