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.

825 lines
21 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. HttpSendRequestA
  9. HttpSendRequestW
  10. HttpSendRequestExA
  11. HttpSendRequestExW
  12. HttpEndRequestA
  13. HttpEndRequestW
  14. HttpWrapSendRequest
  15. Author:
  16. Keith Moore (keithmo) 16-Nov-1994
  17. Revision History:
  18. 29-Apr-97 rfirth
  19. Conversion to FSM
  20. --*/
  21. #include <wininetp.h>
  22. #include <perfdiag.hxx>
  23. #include "httpp.h"
  24. //
  25. // private prototypes
  26. //
  27. PRIVATE
  28. BOOL
  29. HttpWrapSendRequest(
  30. IN HINTERNET hRequest,
  31. IN LPCSTR lpszHeaders OPTIONAL,
  32. IN DWORD dwHeadersLength,
  33. IN LPVOID lpOptional OPTIONAL,
  34. IN DWORD dwOptionalLength,
  35. IN DWORD dwOptionalLengthTotal,
  36. IN AR_TYPE arRequest
  37. );
  38. //
  39. // functions
  40. //
  41. INTERNETAPI_(BOOL) 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_(BOOL) HttpSendRequestW(
  100. IN HINTERNET hRequest,
  101. IN LPCWSTR lpszHeaders OPTIONAL,
  102. IN DWORD dwHeadersLength,
  103. IN LPVOID lpOptional OPTIONAL,
  104. IN DWORD dwOptionalLength
  105. )
  106. /*++
  107. Routine Description:
  108. Sends the specified request to the HTTP server.
  109. Arguments:
  110. hRequest - An open HTTP request handle returned by
  111. HttpOpenRequest()
  112. lpszHeaders - Additional headers to be appended to the request.
  113. This may be NULL if there are no additional
  114. headers to append
  115. dwHeadersLength - The length (in characters) of the additional
  116. headers. If this is -1L and lpszAdditional is
  117. non-NULL, then lpszAdditional is assumed to be
  118. zero terminated (ASCIIZ)
  119. lpOptionalData - Any optional data to send immediately after the
  120. request headers. This is typically used for POST
  121. operations. This may be NULL if there is no
  122. optional data to send
  123. dwOptionalDataLength - The length (in BYTEs) of the optional data. This
  124. may be zero if there is no optional data to send
  125. Return Value:
  126. BOOL
  127. Success - TRUE
  128. Failure - FALSE. For more information call GetLastError(). If the
  129. request was async, then GetLastError() will return
  130. ERROR_IO_PENDING which means that the operation initially
  131. succeeded, and that the caller should wait for the status
  132. callback to discover the final success/failure status
  133. --*/
  134. {
  135. DEBUG_ENTER_API((DBG_API,
  136. Bool,
  137. "HttpSendRequestW",
  138. "%#x, %.80wq, %d, %#x, %d",
  139. hRequest,
  140. lpszHeaders,
  141. dwHeadersLength,
  142. lpOptional,
  143. dwOptionalLength
  144. ));
  145. DWORD dwErr = ERROR_SUCCESS;
  146. BOOL fResult = FALSE;
  147. MEMORYPACKET mpHeaders;
  148. if (!hRequest)
  149. {
  150. dwErr = ERROR_INVALID_HANDLE;
  151. goto cleanup;
  152. }
  153. if (lpszHeaders)
  154. {
  155. ALLOC_MB(lpszHeaders, dwHeadersLength, mpHeaders);
  156. if (!mpHeaders.psStr)
  157. {
  158. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  159. goto cleanup;
  160. }
  161. UNICODE_TO_ANSI(lpszHeaders, mpHeaders);
  162. }
  163. fResult = HttpWrapSendRequest(hRequest, mpHeaders.psStr, mpHeaders.dwSize,
  164. lpOptional, dwOptionalLength, 0, AR_HTTP_SEND_REQUEST);
  165. cleanup:
  166. if (dwErr!=ERROR_SUCCESS)
  167. {
  168. SetLastError(dwErr);
  169. DEBUG_ERROR(HTTP, dwErr);
  170. }
  171. DEBUG_LEAVE_API(fResult);
  172. return fResult;
  173. }
  174. INTERNETAPI_(BOOL) HttpSendRequestExA(
  175. IN HINTERNET hRequest,
  176. IN LPINTERNET_BUFFERSA lpBuffersIn OPTIONAL,
  177. OUT LPINTERNET_BUFFERSA lpBuffersOut OPTIONAL,
  178. IN DWORD dwFlags,
  179. IN DWORD_PTR dwContext
  180. )
  181. /*++
  182. Routine Description:
  183. description-of-function.
  184. Arguments:
  185. hRequest -
  186. lpBuffersIn -
  187. lpBuffersOut -
  188. dwFlags -
  189. dwContext -
  190. Return Value:
  191. WINAPI
  192. --*/
  193. {
  194. DEBUG_ENTER_API((DBG_API,
  195. Bool,
  196. "HttpSendRequestExA",
  197. "%#x, %#x, %#x, %#x, %#x",
  198. hRequest,
  199. lpBuffersIn,
  200. lpBuffersOut,
  201. dwFlags,
  202. dwContext
  203. ));
  204. DWORD error = ERROR_SUCCESS;
  205. LPCSTR lpszHeaders = NULL;
  206. DWORD dwHeadersLength = 0;
  207. LPVOID lpOptional = NULL;
  208. DWORD dwOptionalLength = 0;
  209. DWORD dwOptionalLengthTotal = 0;
  210. BOOL fRet = FALSE;
  211. if ( lpBuffersOut )
  212. {
  213. error = ERROR_INVALID_PARAMETER;
  214. goto quit;
  215. }
  216. if ( lpBuffersIn )
  217. {
  218. if ( IsBadReadPtr(lpBuffersIn, sizeof(INTERNET_BUFFERSA)) ||
  219. lpBuffersIn->dwStructSize != sizeof(INTERNET_BUFFERSA) )
  220. {
  221. error = ERROR_INVALID_PARAMETER;
  222. goto quit;
  223. }
  224. lpszHeaders = lpBuffersIn->lpcszHeader;
  225. dwHeadersLength = lpBuffersIn->dwHeadersLength;
  226. lpOptional = lpBuffersIn->lpvBuffer;
  227. dwOptionalLength = lpBuffersIn->dwBufferLength;
  228. dwOptionalLengthTotal = lpBuffersIn->dwBufferTotal;
  229. }
  230. fRet= HttpWrapSendRequest(
  231. hRequest,
  232. lpszHeaders,
  233. dwHeadersLength,
  234. lpOptional,
  235. dwOptionalLength,
  236. dwOptionalLengthTotal,
  237. AR_HTTP_BEGIN_SEND_REQUEST
  238. );
  239. quit:
  240. if ( error != ERROR_SUCCESS )
  241. {
  242. SetLastError(error);
  243. DEBUG_ERROR(HTTP, error);
  244. fRet = FALSE;
  245. }
  246. DEBUG_LEAVE_API(fRet);
  247. return fRet;
  248. }
  249. INTERNETAPI_(BOOL) HttpSendRequestExW(
  250. IN HINTERNET hRequest,
  251. IN LPINTERNET_BUFFERSW lpBuffersIn OPTIONAL,
  252. OUT LPINTERNET_BUFFERSW lpBuffersOut OPTIONAL,
  253. IN DWORD dwFlags,
  254. IN DWORD_PTR dwContext
  255. )
  256. /*++
  257. Routine Description:
  258. description-of-function.
  259. Arguments:
  260. hRequest -
  261. lpBuffersIn -
  262. lpBuffersOut -
  263. dwFlags -
  264. dwContext -
  265. Return Value:
  266. BOOL
  267. --*/
  268. {
  269. DEBUG_ENTER_API((DBG_API,
  270. Bool,
  271. "HttpSendRequestExW",
  272. "%#x, %#x, %#x, %#x, %#x",
  273. hRequest,
  274. lpBuffersIn,
  275. lpBuffersOut,
  276. dwFlags,
  277. dwContext
  278. ));
  279. DWORD dwErr = ERROR_SUCCESS;
  280. BOOL fResult = FALSE;
  281. MEMORYPACKET mpHeaders;
  282. LPVOID pOptional = NULL;
  283. DWORD dwOptionalLength = 0;
  284. DWORD dwOptionalLengthTotal = 0;
  285. if (!hRequest)
  286. {
  287. dwErr = ERROR_INVALID_HANDLE;
  288. }
  289. else if (lpBuffersOut)
  290. {
  291. dwErr = ERROR_INVALID_PARAMETER;
  292. }
  293. else
  294. {
  295. if ( lpBuffersIn )
  296. {
  297. if (IsBadReadPtr(lpBuffersIn, sizeof(INTERNET_BUFFERS))
  298. ||
  299. (lpBuffersIn->dwStructSize != sizeof(INTERNET_BUFFERSW)))
  300. {
  301. dwErr = ERROR_INVALID_PARAMETER;
  302. goto cleanup;
  303. }
  304. if (lpBuffersIn->lpcszHeader)
  305. {
  306. ALLOC_MB(lpBuffersIn->lpcszHeader, lpBuffersIn->dwHeadersLength, mpHeaders);
  307. if (!mpHeaders.psStr)
  308. {
  309. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  310. goto cleanup;
  311. }
  312. UNICODE_TO_ANSI(lpBuffersIn->lpcszHeader, mpHeaders);
  313. }
  314. pOptional = lpBuffersIn->lpvBuffer;
  315. dwOptionalLength = lpBuffersIn->dwBufferLength;
  316. dwOptionalLengthTotal = lpBuffersIn->dwBufferTotal;
  317. }
  318. fResult = HttpWrapSendRequest(
  319. hRequest,
  320. mpHeaders.psStr,
  321. mpHeaders.dwSize,
  322. pOptional,
  323. dwOptionalLength,
  324. dwOptionalLengthTotal,
  325. AR_HTTP_BEGIN_SEND_REQUEST
  326. );
  327. }
  328. cleanup:
  329. if (dwErr!=ERROR_SUCCESS)
  330. {
  331. SetLastError(dwErr);
  332. DEBUG_ERROR(HTTP, dwErr);
  333. }
  334. DEBUG_LEAVE_API(fResult);
  335. return fResult;
  336. }
  337. INTERNETAPI_(BOOL) HttpEndRequestA(
  338. IN HINTERNET hRequest,
  339. OUT LPINTERNET_BUFFERSA lpBuffersOut OPTIONAL,
  340. IN DWORD dwFlags,
  341. IN DWORD_PTR dwContext
  342. )
  343. /*++
  344. Routine Description:
  345. description-of-function.
  346. Arguments:
  347. hRequest -
  348. lpBuffersOut -
  349. dwFlags -
  350. dwContext -
  351. Return Value:
  352. WINAPI
  353. --*/
  354. {
  355. DEBUG_ENTER_API((DBG_API,
  356. Bool,
  357. "HttpEndRequestA",
  358. "%#x, %#x, %#x, %#x",
  359. hRequest,
  360. lpBuffersOut,
  361. dwFlags,
  362. dwContext
  363. ));
  364. DWORD error = ERROR_SUCCESS;
  365. IN LPCSTR lpszHeaders = NULL;
  366. IN DWORD dwHeadersLength = 0;
  367. IN LPVOID lpOptional = NULL;
  368. IN DWORD dwOptionalLength = 0;
  369. BOOL fRet = FALSE;
  370. if ( lpBuffersOut )
  371. {
  372. error = ERROR_INVALID_PARAMETER;
  373. goto quit;
  374. }
  375. fRet= HttpWrapSendRequest(
  376. hRequest,
  377. NULL,
  378. 0,
  379. NULL,
  380. 0,
  381. 0,
  382. AR_HTTP_END_SEND_REQUEST
  383. );
  384. quit:
  385. if ( error != ERROR_SUCCESS )
  386. {
  387. SetLastError(error);
  388. DEBUG_ERROR(HTTP, error);
  389. fRet = FALSE;
  390. }
  391. DEBUG_LEAVE_API(fRet);
  392. return fRet;
  393. }
  394. INTERNETAPI_(BOOL) HttpEndRequestW(
  395. IN HINTERNET hRequest,
  396. OUT LPINTERNET_BUFFERSW lpBuffersOut OPTIONAL,
  397. IN DWORD dwFlags,
  398. IN DWORD_PTR dwContext
  399. )
  400. /*++
  401. Routine Description:
  402. description-of-function.
  403. Arguments:
  404. hRequest -
  405. lpBuffersOut -
  406. dwFlags -
  407. dwContext -
  408. Return Value:
  409. BOOL
  410. --*/
  411. {
  412. DEBUG_ENTER_API((DBG_API,
  413. Bool,
  414. "HttpEndRequestW",
  415. "%#x, %#x, %#x, %#x",
  416. hRequest,
  417. lpBuffersOut,
  418. dwFlags,
  419. dwContext
  420. ));
  421. DWORD dwErr = ERROR_SUCCESS;
  422. BOOL fResult = FALSE;
  423. if (!hRequest)
  424. {
  425. dwErr = ERROR_INVALID_HANDLE;
  426. }
  427. else if (lpBuffersOut)
  428. {
  429. dwErr = ERROR_INVALID_PARAMETER;
  430. }
  431. else
  432. {
  433. fResult = HttpWrapSendRequest(hRequest, NULL, 0, NULL, 0, 0, AR_HTTP_END_SEND_REQUEST);
  434. }
  435. if (dwErr!=ERROR_SUCCESS)
  436. {
  437. SetLastError(dwErr);
  438. DEBUG_ERROR(HTTP, dwErr);
  439. }
  440. DEBUG_LEAVE_API(fResult);
  441. return fResult;
  442. }
  443. PRIVATE
  444. BOOL
  445. HttpWrapSendRequest(
  446. IN HINTERNET hRequest,
  447. IN LPCSTR lpszHeaders OPTIONAL,
  448. IN DWORD dwHeadersLength,
  449. IN LPVOID lpOptional OPTIONAL,
  450. IN DWORD dwOptionalLength,
  451. IN DWORD dwOptionalLengthTotal,
  452. IN AR_TYPE arRequest
  453. )
  454. /*++
  455. Routine Description:
  456. Sends the specified request to the HTTP server.
  457. Arguments:
  458. hRequest - An open HTTP request handle returned by
  459. HttpOpenRequest()
  460. lpszHeaders - Additional headers to be appended to the request.
  461. This may be NULL if there are no additional
  462. headers to append
  463. dwHeadersLength - The length (in characters) of the additional
  464. headers. If this is -1L and lpszAdditional is
  465. non-NULL, then lpszAdditional is assumed to be
  466. zero terminated (ASCIIZ)
  467. lpOptionalData - Any optional data to send immediately after the
  468. request headers. This is typically used for POST
  469. operations. This may be NULL if there is no
  470. optional data to send
  471. dwOptionalDataLength - The length (in BYTEs) of the optional data. This
  472. may be zero if there is no optional data to send
  473. dwOptionalLengthTotal - Total length need to be sent for File Upload.
  474. arRequest - Which API the caller is making,
  475. assumed to be HttpEndRequestA, HttpSendRequestExA, or
  476. HttpSendRequestA
  477. Return Value:
  478. BOOL
  479. Success - TRUE
  480. Failure - FALSE. For more information call GetLastError(). If the
  481. request was async, then GetLastError() will return
  482. ERROR_IO_PENDING which means that the operation initially
  483. succeeded, and that the caller should wait for the status
  484. callback to discover the final success/failure status
  485. Comments:
  486. --*/
  487. {
  488. DEBUG_ENTER((DBG_HTTP,
  489. Bool,
  490. "HttpWrapSendRequest",
  491. "%#x, %.80q, %d, %#x, %d, %d",
  492. hRequest,
  493. lpszHeaders,
  494. dwHeadersLength,
  495. lpOptional,
  496. dwOptionalLength,
  497. dwOptionalLengthTotal
  498. ));
  499. PERF_ENTER(HttpWrapSendRequest);
  500. DWORD error = ERROR_SUCCESS;
  501. HINTERNET hRequestMapped = NULL;
  502. BOOL bDeref = TRUE;
  503. if (!GlobalDataInitialized) {
  504. error = ERROR_INTERNET_NOT_INITIALIZED;
  505. goto done;
  506. }
  507. //
  508. // we will need the thread info for several items
  509. //
  510. LPINTERNET_THREAD_INFO lpThreadInfo;
  511. lpThreadInfo = InternetGetThreadInfo();
  512. if (lpThreadInfo == NULL) {
  513. error = ERROR_INTERNET_INTERNAL_ERROR;
  514. goto done;
  515. }
  516. //
  517. // the only FSMs that can come before this one are InternetOpenUrl() or
  518. // HttpSendRequest() when we are performing nested send for https://
  519. // tunnelling through proxy
  520. //
  521. INET_ASSERT((lpThreadInfo->Fsm == NULL)
  522. || (lpThreadInfo->Fsm->GetType() == FSM_TYPE_PARSE_HTTP_URL)
  523. || (lpThreadInfo->Fsm->GetType() == FSM_TYPE_OPEN_PROXY_TUNNEL)
  524. );
  525. INET_ASSERT( arRequest == AR_HTTP_SEND_REQUEST ||
  526. arRequest == AR_HTTP_BEGIN_SEND_REQUEST ||
  527. arRequest == AR_HTTP_END_SEND_REQUEST );
  528. //
  529. // map the handle
  530. //
  531. error = MapHandleToAddress(hRequest, (LPVOID *)&hRequestMapped, FALSE);
  532. if ((error != ERROR_SUCCESS) && (hRequestMapped == NULL)) {
  533. goto quit;
  534. }
  535. //
  536. // Cast it to the object that we know. We are going to do caching
  537. // semantics with this
  538. //
  539. HTTP_REQUEST_HANDLE_OBJECT * pRequest;
  540. pRequest = (HTTP_REQUEST_HANDLE_OBJECT *)hRequestMapped;
  541. //
  542. // set the context and handle info & reset the error variables
  543. //
  544. _InternetSetContext(lpThreadInfo,
  545. ((INTERNET_HANDLE_OBJECT *)hRequestMapped)->GetContext()
  546. );
  547. _InternetSetObjectHandle(lpThreadInfo, hRequest, hRequestMapped);
  548. _InternetClearLastError(lpThreadInfo);
  549. //
  550. // quit now if the handle was invalid
  551. //
  552. if (error != ERROR_SUCCESS) {
  553. goto quit;
  554. }
  555. //
  556. // use RIsHandleLocal() to discover 4 things:
  557. //
  558. // 1. Handle is valid
  559. // 2. Handle is of expected type (HTTP Request in this case)
  560. // 3. Handle is local or remote
  561. // 4. Handle supports async I/O
  562. //
  563. BOOL isLocal;
  564. BOOL isAsync;
  565. error = RIsHandleLocal(hRequestMapped,
  566. &isLocal,
  567. &isAsync,
  568. TypeHttpRequestHandle
  569. );
  570. if (error != ERROR_SUCCESS) {
  571. goto quit;
  572. }
  573. //
  574. // For SEND_REQUEST, and BEGIN_SEND_REQUEST, we need
  575. // to do some basic initalization
  576. //
  577. if ( arRequest == AR_HTTP_SEND_REQUEST ||
  578. arRequest == AR_HTTP_BEGIN_SEND_REQUEST)
  579. {
  580. BOOL fGoneOffline = FALSE;
  581. error = pRequest->InitBeginSendRequest(lpszHeaders,
  582. dwHeadersLength,
  583. &lpOptional,
  584. &dwOptionalLength,
  585. dwOptionalLengthTotal,
  586. &fGoneOffline
  587. );
  588. if ( error != ERROR_SUCCESS || fGoneOffline )
  589. {
  590. if ( error == ERROR_INTERNET_CACHE_SUCCESS )
  591. {
  592. error = ERROR_SUCCESS;
  593. }
  594. goto quit;
  595. }
  596. }
  597. //
  598. // send the request to the server. This may involve redirections and user
  599. // authentication
  600. //
  601. //error = DoFsm(new CFsm_HttpSendRequest(lpOptional, dwOptionalLength, pRequest, arRequest));
  602. //if (error == ERROR_IO_PENDING) {
  603. // bDeref = FALSE;
  604. //}
  605. CFsm_HttpSendRequest * pFsm;
  606. pFsm = new CFsm_HttpSendRequest(lpOptional, dwOptionalLength, pRequest, arRequest);
  607. if (pFsm != NULL) {
  608. if (isAsync && !lpThreadInfo->IsAsyncWorkerThread) {
  609. error = pFsm->QueueWorkItem();
  610. } else {
  611. error = DoFsm(pFsm);
  612. }
  613. if (error == ERROR_IO_PENDING) {
  614. bDeref = FALSE;
  615. }
  616. } else {
  617. error = ERROR_NOT_ENOUGH_MEMORY;
  618. }
  619. quit:
  620. //
  621. // if we went async don't deref the handle
  622. //
  623. if (bDeref && (hRequestMapped != NULL)) {
  624. DereferenceObject((LPVOID)hRequestMapped);
  625. }
  626. done:
  627. BOOL success = TRUE;
  628. // SetLastError must be called after PERF_LEAVE !!!
  629. PERF_LEAVE(HttpWrapSendRequest);
  630. if (error != ERROR_SUCCESS) {
  631. SetLastError(error);
  632. DEBUG_ERROR(HTTP, error);
  633. success = FALSE;
  634. }
  635. DEBUG_LEAVE(success);
  636. return success;
  637. }