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.

3059 lines
89 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1995.
  5. //
  6. // File: cnethttp.cxx
  7. //
  8. // Contents:
  9. //
  10. // Classes:
  11. //
  12. // Functions:
  13. //
  14. // History: 2-06-96 JohannP (Johann Posch) Created
  15. //
  16. //----------------------------------------------------------------------------
  17. #include <iapp.h>
  18. #include "shlwapip.h"
  19. #ifndef unix
  20. #include "..\trans\transact.hxx"
  21. #include "..\trans\oinet.hxx"
  22. #else
  23. #include "../trans/transact.hxx"
  24. #include "../trans/oinet.hxx"
  25. #endif /* unix */
  26. PerfDbgTag(tagCINetHttp, "Urlmon", "Log CINetHttp", DEB_PROT);
  27. extern LPSTR g_pszUAInfoString;
  28. static CHAR gszAcceptEncHeaders[] = "Accept-Encoding: gzip, deflate";
  29. // http specifics
  30. static char vszGet[] = "GET";
  31. static char vszPost[] = "POST";
  32. static char vszPut[] = "PUT";
  33. static char vszAttachment[] = "attachment";
  34. static char vszFileName[] = "filename";
  35. static DWORD dwLstError;
  36. DWORD GetRedirectSetting();
  37. // list of content-type we should not apply content-encoding onto it.
  38. static LPSTR vszIgnoreContentEnc[] =
  39. {
  40. "application/x-tar"
  41. ,"x-world/x-vrml"
  42. ,"application/zip"
  43. ,"application/x-gzip"
  44. ,"application/x-zip-compressed"
  45. ,"application/x-compress"
  46. ,"application/x-compressed"
  47. ,"application/x-spoon"
  48. , 0
  49. };
  50. BOOL IgnoreContentEncoding(LPSTR szContentType, LPSTR szEnc, LPSTR szAccept)
  51. {
  52. DEBUG_ENTER((DBG_APP,
  53. Bool,
  54. "IgnoreContentEncoding",
  55. "%.80q, %.80q, %.80q",
  56. szContentType, szEnc, szAccept
  57. ));
  58. BOOL bRet = FALSE;
  59. if( szEnc && szAccept && !StrStrI(szAccept, szEnc) )
  60. {
  61. //
  62. // some of the old web server will ignore the schemas indicated at
  63. // Accept-Endocing: header, we need to add another check here
  64. // to make sure the server returned content-encoding is the
  65. // one we supported, otherwise, we will not init the decoder
  66. //
  67. bRet = TRUE;
  68. }
  69. if( !bRet )
  70. {
  71. for( int i = 0; vszIgnoreContentEnc[i]; i++)
  72. {
  73. if(!StrCmpI(szContentType, vszIgnoreContentEnc[i]) )
  74. {
  75. bRet = TRUE;
  76. break;
  77. }
  78. }
  79. }
  80. DEBUG_LEAVE(bRet);
  81. return bRet;
  82. }
  83. //+---------------------------------------------------------------------------
  84. //
  85. // Function: GetRedirectSetting
  86. //
  87. // Synopsis: Reads the registry UrlMon Setting of Redirect
  88. //
  89. // Arguments: (none)
  90. //
  91. // Returns: 0 if redirect should be done by WinINet,
  92. // 1 if should be done by UrlMon
  93. //
  94. // History: 4-22-96 JohannP (Johann Posch) Created
  95. //
  96. // Notes:
  97. //
  98. //----------------------------------------------------------------------------
  99. DWORD GetRedirectSetting()
  100. {
  101. DEBUG_ENTER((DBG_APP,
  102. Dword,
  103. "GetRedirectSetting",
  104. NULL
  105. ));
  106. HKEY hUrlMonKey = NULL;
  107. DWORD dwType;
  108. static DWORD dwValue = 0xffffffff;
  109. if (dwValue == 0xffffffff)
  110. {
  111. DWORD dwValueLen = sizeof(DWORD);
  112. dwValue = 0;
  113. #define szUrlMonKey "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\UrlMon Settings"
  114. #define szRedirect "Redirect"
  115. if (RegOpenKeyEx(HKEY_CURRENT_USER, szUrlMonKey, 0, KEY_QUERY_VALUE, &hUrlMonKey) == ERROR_SUCCESS)
  116. {
  117. if (RegQueryValueEx(hUrlMonKey, szRedirect, NULL, &dwType, (LPBYTE)&dwValue, &dwValueLen) != ERROR_SUCCESS)
  118. {
  119. dwValue = 0;
  120. }
  121. RegCloseKey(hUrlMonKey);
  122. }
  123. }
  124. DEBUG_LEAVE(dwValue);
  125. return dwValue;
  126. }
  127. // max version strlen = (5)"HTTP/" + (4)digits + (1)'.' + (4)digits + (1)'\0'
  128. #define MAXVERSIONLEN 15
  129. BOOL RequestUsedHttp10(
  130. IN HINTERNET hHttpRequest
  131. )
  132. {
  133. DEBUG_ENTER((DBG_APP,
  134. Bool,
  135. "RequestUsedHttp10",
  136. "%#x",
  137. hHttpRequest
  138. ));
  139. char lpszHttpVersion[MAXVERSIONLEN];
  140. DWORD dwLen = MAXVERSIONLEN;
  141. BOOL fRet = FALSE;
  142. if (HttpQueryInfo(
  143. hHttpRequest,
  144. HTTP_QUERY_FLAG_REQUEST_HEADERS | HTTP_QUERY_VERSION,
  145. (LPVOID)lpszHttpVersion,
  146. &dwLen,
  147. NULL))
  148. {
  149. if (0 == StrCmpNI("HTTP/1.0", lpszHttpVersion, dwLen))
  150. fRet = TRUE;
  151. }
  152. DEBUG_LEAVE(fRet);
  153. return fRet;
  154. }
  155. //+---------------------------------------------------------------------------
  156. //
  157. // Method: CINetHttp::CINetHttp
  158. //
  159. // Synopsis:
  160. //
  161. // Arguments: (none)
  162. //
  163. // Returns:
  164. //
  165. // History: 2-06-96 JohannP (Johann Posch) Created
  166. //
  167. // Notes:
  168. //
  169. //----------------------------------------------------------------------------
  170. CINetHttp::CINetHttp(REFCLSID rclsid, IUnknown *pUnkOuter) : CINet(rclsid,pUnkOuter)
  171. {
  172. DEBUG_ENTER((DBG_APP,
  173. None,
  174. "CINetHttp::CINetHttp",
  175. "this=%#x, %#x, %#x",
  176. this, &rclsid, pUnkOuter
  177. ));
  178. PerfDbgLog(tagCINetHttp, this, "+CINetHttp::CINetHttp");
  179. _pHttpNeg = NULL;
  180. _pHttpNeg2 = NULL;
  181. _dwIsA = DLD_PROTOCOL_HTTP;
  182. _dwBufferSize = 0;
  183. _pBuffer = 0;
  184. _pszVerb = 0;
  185. _f2ndCacheKeySet = FALSE;
  186. PerfDbgLog(tagCINetHttp, this, "-CINetHttp::CINetHttp");
  187. DEBUG_LEAVE(0);
  188. }
  189. //----------------------------------------------------------------------------
  190. //
  191. // Method: CINetHttp::~CINetHttp
  192. //
  193. // Synopsis:
  194. //
  195. // Arguments: (none)
  196. //
  197. // Returns:
  198. //
  199. // History: 2-06-96 JohannP (Johann Posch) Created
  200. //
  201. // Notes:
  202. //
  203. //----------------------------------------------------------------------------
  204. CINetHttp::~CINetHttp()
  205. {
  206. DEBUG_ENTER((DBG_APP,
  207. None,
  208. "CINetHttp::~CINetHttp",
  209. "this=%#x",
  210. this
  211. ));
  212. PerfDbgLog(tagCINetHttp, this, "+CINetHttp::~CINetHttp");
  213. PProtAssert(( !_hRequest ));
  214. PProtAssert(( !_hServer ));
  215. delete [] _pBuffer;
  216. delete [] _pszHeader;
  217. delete [] _pszSendHeader;
  218. delete [] _pwzAddHeader;
  219. delete [] _pszVerb;
  220. if (_pbRootSecurityId != INVALID_P_ROOT_SECURITY_ID)
  221. delete [] _pbRootSecurityId;
  222. PProtAssert((_pHttpNeg == NULL));
  223. PProtAssert((_pHttpNeg2 == NULL));
  224. PProtAssert((_pWindow == NULL));
  225. PProtAssert(( _pHttSecurity == NULL));
  226. PerfDbgLog(tagCINetHttp, this, "-CINetHttp::~CINetHttp");
  227. DEBUG_LEAVE(0);
  228. }
  229. //+---------------------------------------------------------------------------
  230. //
  231. // Method: CINetHttp::INetAsyncOpenRequest
  232. //
  233. // Synopsis:
  234. //
  235. // Arguments: (none)
  236. //
  237. // Returns:
  238. //
  239. // History: 1-27-96 JohannP (Johann Posch) Created
  240. //
  241. // Notes:
  242. //
  243. //----------------------------------------------------------------------------
  244. HRESULT CINetHttp::INetAsyncOpenRequest()
  245. {
  246. DEBUG_ENTER((DBG_APP,
  247. Hresult,
  248. "CINetHttp::INetAsyncOpenRequest",
  249. "this=%#x",
  250. this
  251. ));
  252. PerfDbgLog1(tagCINetHttp, this, "+CINetHttp::INetAsyncOpenRequest (_szObject:%s)", GetObjectName());
  253. HRESULT hr = NOERROR;
  254. DWORD dwBindF = 0;
  255. const ULONG culSize = 256;
  256. ULONG ulSize = culSize;
  257. LPCSTR rgszAcceptStr[culSize] = { 0 };
  258. LPWSTR rgwzStr[culSize];
  259. SetINetState(INetState_PROTOPEN_REQUEST);
  260. PProtAssert((g_hSession != NULL));
  261. PProtAssert((GetStatePending() == NOERROR));
  262. if (_pOIBindInfo)
  263. {
  264. LPWSTR *pwzStr;
  265. IEnumString *pEnumString = NULL;
  266. ULONG ulCount = culSize;
  267. hr = _pOIBindInfo->GetBindString(BINDSTRING_ACCEPT_MIMES, (LPWSTR *)rgwzStr, ulSize, &ulCount);
  268. if (hr == NOERROR)
  269. {
  270. ULONG c = 0;
  271. for (c = 0; c < ulCount; c++)
  272. {
  273. rgszAcceptStr[c] = (LPCSTR) DupW2A(rgwzStr[c]);
  274. delete rgwzStr[c];
  275. rgwzStr[c] = 0;
  276. }
  277. rgszAcceptStr[c] = 0;
  278. }
  279. else
  280. if( hr == INET_E_USE_DEFAULT_SETTING )
  281. {
  282. rgszAcceptStr[0] = (LPCSTR) DupW2A(L"*/*");
  283. rgszAcceptStr[1] = NULL;
  284. hr = NOERROR;
  285. }
  286. }
  287. if (hr != NOERROR)
  288. {
  289. hr = INET_E_NO_VALID_MEDIA;
  290. _hrError = INET_E_NO_VALID_MEDIA;
  291. }
  292. else if (!_hServer)
  293. {
  294. // the download was probably aborted
  295. if (_hrError == NOERROR)
  296. {
  297. SetBindResult(ERROR_INVALID_HANDLE, hr);
  298. hr = _hrError = INET_E_CANNOT_CONNECT;
  299. }
  300. else
  301. {
  302. hr = _hrError;
  303. }
  304. }
  305. else
  306. {
  307. PProtAssert((_hServer));
  308. //PProtAssert((ppszAcceptStr && *ppszAcceptStr));
  309. #if DBG==1
  310. {
  311. LPSTR *pszMime = (LPSTR *) &rgszAcceptStr;
  312. while (*pszMime)
  313. {
  314. PerfDbgLog1(tagCINetHttp, this, "=== CTransData::GetAcceptStr (szMime:%s)", *pszMime);
  315. pszMime++;
  316. }
  317. }
  318. #endif
  319. dwBindF = GetBindFlags();
  320. if (dwBindF & BINDF_IGNORESECURITYPROBLEM)
  321. {
  322. _dwOpenFlags |= INTERNET_FLAG_IGNORE_CERT_CN_INVALID;
  323. _dwOpenFlags |= INTERNET_FLAG_IGNORE_CERT_DATE_INVALID;
  324. _dwOpenFlags |= INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTPS;
  325. _dwOpenFlags |= INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTP;
  326. }
  327. if (dwBindF & BINDF_ENFORCERESTRICTED)
  328. {
  329. _dwOpenFlags |= INTERNET_FLAG_RESTRICTED_ZONE;
  330. }
  331. if (GetRedirectSetting() != 0)
  332. {
  333. DbgLog(tagCINetHttp, this, "=== CINet::INetAsyncOpenRequest redirect done by UrlMon!");
  334. _dwOpenFlags |= INTERNET_FLAG_NO_AUTO_REDIRECT;
  335. }
  336. else
  337. {
  338. DbgLog(tagCINetHttp, this, "=== CINet::INetAsyncOpenRequest redirect done by WinINet!");
  339. }
  340. //
  341. // we always request keep-alive
  342. //
  343. _dwOpenFlags |= INTERNET_FLAG_KEEP_CONNECTION;
  344. //
  345. // Notify wininet if this is a multipart upload so it doesn't
  346. // add a terminating 0x0d 0x0a to the first send
  347. //
  348. BINDINFO *pBndInfo = GetBindInfo();
  349. if (IsUpLoad()
  350. // Add in extra check to make TYMED_ISTREAM work the same as
  351. // TYMED_HGLOBAL for verbs that require a body, other than POST.
  352. // We might consider doing away with this IF statement in the future:
  353. && (pBndInfo->dwBindVerb == BINDVERB_POST))
  354. {
  355. _dwOpenFlags |= INTERNET_FLAG_NO_AUTO_REDIRECT;
  356. //BUGBUG: is the flag below needed?
  357. //_dwOpenFlags |= INTERNET_FLAG_MULTIPART;
  358. }
  359. PrivAddRef(TRUE);
  360. SetStatePending(E_PENDING);
  361. _HandleStateRequest = HandleState_Pending;
  362. HINTERNET hRequestTmp = HttpOpenRequest(
  363. _hServer, // hHttpSession
  364. GetVerb(), // lpszVerb
  365. GetObjectName(), // lpszObjectName
  366. NULL, //HTTP_VERSION, // lpszVersion
  367. NULL, // lpszReferer
  368. rgszAcceptStr, // lplpszAcceptTypes
  369. _dwOpenFlags, // flag
  370. (DWORD_PTR) this // context
  371. );
  372. if ( hRequestTmp == 0)
  373. {
  374. dwLstError = GetLastError();
  375. if (dwLstError == ERROR_IO_PENDING)
  376. {
  377. // wait async for the handle
  378. hr = E_PENDING;
  379. }
  380. else
  381. {
  382. PrivRelease(TRUE);
  383. SetStatePending(NOERROR);
  384. hr = _hrError = INET_E_RESOURCE_NOT_FOUND;
  385. SetBindResult(dwLstError,hr);
  386. }
  387. }
  388. else
  389. {
  390. _hRequest = hRequestTmp;
  391. SetStatePending(NOERROR);
  392. _HandleStateRequest = HandleState_Initialized;
  393. if (_fUTF8hack)
  394. {
  395. DWORD dwSendUTF8 = 1;
  396. InternetSetOption(_hRequest, INTERNET_OPTION_SEND_UTF8_SERVERNAME_TO_PROXY, &dwSendUTF8, sizeof(DWORD));
  397. InternetSetOption(_hRequest, INTERNET_OPTION_CODEPAGE, &_dwServerCodePage, sizeof(DWORD));
  398. }
  399. hr = INetAsyncSendRequest();
  400. }
  401. {
  402. LPSTR *pszMime = (LPSTR *) &rgszAcceptStr;
  403. while (*pszMime)
  404. {
  405. LPSTR pszDel = *pszMime;
  406. delete pszDel;
  407. pszMime++;
  408. }
  409. }
  410. }
  411. PerfDbgLog1(tagCINetHttp, this, "-CINetHttp::INetAsyncOpenRequest (hr:%lx)", hr);
  412. DEBUG_LEAVE(hr);
  413. return hr;
  414. }
  415. //+---------------------------------------------------------------------------
  416. //
  417. // Method: CINetHttp::INetAsyncSendRequest
  418. //
  419. // Synopsis:
  420. //
  421. // Arguments: (none)
  422. //
  423. // Returns:
  424. //
  425. // History: 1-27-96 JohannP (Johann Posch) Created
  426. //
  427. // Notes:
  428. //
  429. //----------------------------------------------------------------------------
  430. HRESULT CINetHttp::INetAsyncSendRequest()
  431. {
  432. DEBUG_ENTER((DBG_APP,
  433. Hresult,
  434. "CINetHttp::INetAsyncSendRequest",
  435. "this=%#x",
  436. this
  437. ));
  438. PerfDbgLog(tagCINetHttp, this, "+CINetHttp::INetAsyncSendRequest");
  439. HRESULT hr = NOERROR;
  440. BOOL fRestarted;
  441. BOOL fRet;
  442. PProtAssert((GetStatePending() == NOERROR));
  443. SetINetState(INetState_SEND_REQUEST);
  444. LPVOID pBuffer = 0;
  445. DWORD dwBufferSize = 0;
  446. LPSTR szVerb = GetVerb();
  447. //
  448. // BUGBUG: move this into GetAdditionalHeader
  449. //
  450. if (_fRedirected == TRUE || (_cbProxyAuthenticate + _cbAuthenticate))
  451. {
  452. if (_pszSendHeader)
  453. {
  454. delete _pszSendHeader;
  455. _pszSendHeader = NULL;
  456. }
  457. }
  458. if (_fRedirected == FALSE && !(_cbProxyAuthenticate + _cbAuthenticate))
  459. {
  460. GetAdditionalHeader();
  461. }
  462. if (_fRedirected == FALSE || _fP2PRedirected )
  463. {
  464. // Note: the buffer returned here will be freed
  465. // by the destructor
  466. GetDataToSend(&pBuffer, &dwBufferSize);
  467. _fP2PRedirected = FALSE;
  468. }
  469. // Call HttpNeg only the first time in case of authentication
  470. // i.e. both Auth counts == 0 ?
  471. if (!(_cbAuthenticate || _cbProxyAuthenticate)) {
  472. //BUGBUG: does BeginingTrans need to be called for
  473. // redirect and authentication resends?
  474. if (_fRedirected == FALSE)
  475. hr = HttpNegBeginningTransaction();
  476. // Note: the header is appended to the AddHeader
  477. }
  478. HttpNegGetRootSecurityId();
  479. LONG lThirdParty;
  480. if (IsThirdPartyUrl(GetUrl()))
  481. {
  482. lThirdParty = 1;
  483. //MessageBoxW( 0, GetUrl(), L"cnethttp: THIRDPARTY!", 0 );
  484. InternetSetOption(_hRequest, INTERNET_OPTION_COOKIES_3RD_PARTY, &lThirdParty, sizeof(LONG));
  485. }
  486. else
  487. {
  488. lThirdParty = 0;
  489. //MessageBoxW( 0, GetUrl(), L"cnethttp: NOT THIRDPARTY!", 0 );
  490. InternetSetOption(_hRequest, INTERNET_OPTION_COOKIES_3RD_PARTY, &lThirdParty, sizeof(LONG));
  491. }
  492. if (hr == E_ABORT)
  493. {
  494. _hrError = hr;
  495. SetBindResult(ERROR_CANCELLED,hr);
  496. }
  497. else
  498. {
  499. PerfDbgLog1(tagCINetHttp, this, "+CINetHttp::INetAsyncSendRequest HttpSendRequest (_pszSendHeader:%s)", XDBG(_pszSendHeader,""));
  500. if (GetBindInfo()->dwBindVerb == BINDVERB_POST && !_f2ndCacheKeySet)
  501. {
  502. // WININET request: send SECONDARY_CACHE_KEY only once
  503. ULONG ulCount = 0;
  504. LPWSTR pwzPostCookieStr = 0;
  505. HRESULT hr1 = _pOIBindInfo->GetBindString(BINDSTRING_POST_COOKIE, (LPWSTR *)&pwzPostCookieStr, 1, &ulCount);
  506. if ((hr1 == NOERROR) && pwzPostCookieStr)
  507. {
  508. // BUGBUG: trident return s_ok and no string
  509. PProtAssert((pwzPostCookieStr));
  510. LPSTR pszStr = DupW2A(pwzPostCookieStr);
  511. if (pszStr)
  512. {
  513. _f2ndCacheKeySet = TRUE;
  514. InternetSetOption(_hRequest, INTERNET_OPTION_SECONDARY_CACHE_KEY, pszStr, strlen(pszStr));
  515. delete pszStr;
  516. }
  517. else
  518. {
  519. hr = E_OUTOFMEMORY;
  520. _hrError = INET_E_DOWNLOAD_FAILURE;
  521. SetBindResult(hr,hr);
  522. }
  523. delete pwzPostCookieStr;
  524. }
  525. }
  526. /************ enable this after wininet sniff checked in *******
  527. // set option for data sniff
  528. DWORD dwDataSniff = 1;
  529. InternetSetOption(_hRequest, INTERNET_OPTION_DATASNIFF, &dwDataSniff, sizeof(DWORD));
  530. ****************************************************************/
  531. InternetSetOption(_hRequest, INTERNET_OPTION_REQUEST_PRIORITY, &_nPriority, sizeof(LONG));
  532. if (_fRedirected || !_fUTF8hack)
  533. {
  534. /*
  535. This is used in wininet now only to convert the MBCS servername supplied to UTF8
  536. to send to the proxy if needed
  537. */
  538. InternetSetOption(_hRequest, INTERNET_OPTION_CODEPAGE, &_BndInfo.dwCodePage, sizeof(DWORD));
  539. }
  540. SetStatePending(E_PENDING);
  541. if (hr == NOERROR)
  542. {
  543. if (IsUpLoad())
  544. {
  545. // post verb
  546. // DWORD dwSendFlags = HSR_ASYNC | HSR_CHUNKED | HSR_INITIATE;
  547. DWORD dwSendFlags = HSR_CHUNKED | HSR_INITIATE;
  548. DWORD dwSendContext = 0;
  549. if (!_pStm)
  550. {
  551. BINDINFO *pBI = GetBindInfo();
  552. if (pBI && pBI->stgmedData.tymed == TYMED_ISTREAM)
  553. {
  554. _pStm = pBI->stgmedData.pstm;
  555. }
  556. }
  557. if (_pStm)
  558. {
  559. hr = GetNextSendBuffer(&_inetBufferSend,_pStm, TRUE);
  560. }
  561. fRet = HttpSendRequestExA(
  562. _hRequest // IN HINTERNET hRequest,
  563. ,&_inetBufferSend // IN LPINTERNET_BUFFERSA lpBuffersIn OPTIONAL,
  564. , NULL // OUT lpBuffersOut not used
  565. ,dwSendFlags // IN DWORD dwFlags,
  566. ,dwSendContext // IN DWORD dwContext
  567. );
  568. }
  569. else
  570. {
  571. DWORD dwError;
  572. // Allow ERROR_INTERNET_INSERT_CDROM to be returned from HttpSendRequest
  573. #ifdef MSNJIT
  574. DWORD dwErrorMask = INTERNET_ERROR_MASK_INSERT_CDROM | INTERNET_ERROR_MASK_COMBINED_SEC_CERT | INTERNET_ERROR_MASK_NEED_MSN_SSPI_PKG;
  575. #else
  576. DWORD dwErrorMask = INTERNET_ERROR_MASK_INSERT_CDROM | INTERNET_ERROR_MASK_COMBINED_SEC_CERT;
  577. #endif
  578. dwErrorMask = dwErrorMask | INTERNET_ERROR_MASK_LOGIN_FAILURE_DISPLAY_ENTITY_BODY;
  579. InternetSetOption(_hRequest, INTERNET_OPTION_ERROR_MASK, &dwErrorMask, sizeof(DWORD));
  580. fRet = HttpSendRequest(_hRequest,
  581. _pszSendHeader, // additional headers
  582. (_pszSendHeader) ? (ULONG)-1L : 0L, // size of additional headers data
  583. pBuffer, // Optional data (POST or put)
  584. dwBufferSize); // optional data length
  585. PerfDbgLog(tagCINetHttp, this, "-CINetHttp::INetAsyncSendRequest HttpSendRequest");
  586. } // end else
  587. if (fRet == FALSE)
  588. {
  589. dwLstError = GetLastError();
  590. if (dwLstError == ERROR_IO_PENDING)
  591. {
  592. // wait async for the handle
  593. hr = E_PENDING;
  594. }
  595. else if (dwLstError == ERROR_INTERNET_INSERT_CDROM)
  596. {
  597. _hrINet = INET_E_AUTHENTICATION_REQUIRED;
  598. _dwSendRequestResult = ERROR_INTERNET_INSERT_CDROM;
  599. _lpvExtraSendRequestResult = NULL;
  600. TransitState(INetState_DISPLAY_UI, TRUE);
  601. hr = E_PENDING;
  602. fRet = TRUE;
  603. }
  604. else
  605. {
  606. SetStatePending(NOERROR);
  607. hr = _hrError = INET_E_DOWNLOAD_FAILURE;
  608. SetBindResult(dwLstError,hr);
  609. PerfDbgLog3(tagCINetHttp, this, "CINetHttp::INetAsyncSendRequest (fRet:%d, _hrError:%lx, LstError:%ld)", fRet, _hrError, dwLstError);
  610. }
  611. }
  612. else
  613. {
  614. SetStatePending(NOERROR);
  615. // in case of redirect, we need to reset all the
  616. // _dwSendRequestResult from previous callback
  617. _dwSendRequestResult = 0;
  618. _lpvExtraSendRequestResult = NULL;
  619. hr = INetQueryInfo();
  620. }
  621. }
  622. }
  623. if (_hrError != INET_E_OK)
  624. {
  625. // we need to terminate here
  626. ReportResultAndStop(hr);
  627. }
  628. PerfDbgLog1(tagCINetHttp, this, "-CINetHttp::INetAsyncSendRequest (hr:%lx)", hr);
  629. DEBUG_LEAVE(hr);
  630. return hr;
  631. }
  632. //+---------------------------------------------------------------------------
  633. //
  634. // Method: CINetHttp::QueryStatusOnResponse
  635. //
  636. // Synopsis:
  637. //
  638. // Arguments: (none)
  639. //
  640. // Returns:
  641. //
  642. // History: 2-06-96 JohannP (Johann Posch) Created
  643. //
  644. // Notes:
  645. //
  646. //----------------------------------------------------------------------------
  647. HRESULT CINetHttp::QueryStatusOnResponse()
  648. {
  649. DEBUG_ENTER((DBG_APP,
  650. Hresult,
  651. "CINetHttp::QueryStatusOnResponse",
  652. "this=%#x",
  653. this
  654. ));
  655. PerfDbgLog(tagCINetHttp, this, "+CINetHttp::QueryStatusOnResponse");
  656. HRESULT hr = NOERROR;
  657. DWORD dwStatus;
  658. char szBuffer[max(2 * MAX_URL_SIZE, 400)];
  659. DWORD cbBufferLen = sizeof(szBuffer);
  660. DWORD cbLen = cbBufferLen;
  661. if (_dwSendRequestResult)
  662. {
  663. // handle the sendrequest result
  664. // zone crossing
  665. switch (_dwSendRequestResult)
  666. {
  667. case ERROR_INTERNET_SEC_CERT_DATE_INVALID :
  668. case ERROR_INTERNET_SEC_CERT_CN_INVALID :
  669. case ERROR_INTERNET_HTTP_TO_HTTPS_ON_REDIR :
  670. case ERROR_INTERNET_HTTPS_TO_HTTP_ON_REDIR :
  671. case ERROR_INTERNET_HTTPS_HTTP_SUBMIT_REDIR :
  672. case ERROR_HTTP_REDIRECT_NEEDS_CONFIRMATION :
  673. case ERROR_INTERNET_INVALID_CA :
  674. case ERROR_INTERNET_CLIENT_AUTH_CERT_NEEDED :
  675. case ERROR_INTERNET_FORTEZZA_LOGIN_NEEDED :
  676. case ERROR_INTERNET_SEC_CERT_ERRORS :
  677. case ERROR_INTERNET_SEC_CERT_REV_FAILED :
  678. case ERROR_INTERNET_SEC_CERT_REVOKED :
  679. {
  680. hr = HttpSecurity(_dwSendRequestResult);
  681. if ((hr != NOERROR) && (hr != E_PENDING))
  682. {
  683. _hrError = INET_E_AUTHENTICATION_REQUIRED;
  684. }
  685. else
  686. {
  687. _hrError = INET_E_OK;
  688. }
  689. }
  690. break;
  691. case ERROR_INTERNET_LOGIN_FAILURE_DISPLAY_ENTITY_BODY :
  692. {
  693. _hrError = INET_E_OK;
  694. hr = NOERROR;
  695. }
  696. break;
  697. #ifdef MSNJIT
  698. case ERROR_INTERNET_NEED_MSN_SSPI_PKG :
  699. {
  700. const GUID MSN_AUTH_GUID =
  701. { 0x6fab99d0, 0xbab8, 0x11d1, {0x99, 0x4a, 0x00, 0xc0, 0x4f, 0x98, 0xbb, 0xc9} };
  702. HWND hWnd = NULL;
  703. DWORD dwJITFlags = 0;
  704. uCLSSPEC classpec;
  705. classpec.tyspec=TYSPEC_TYPELIB;
  706. classpec.tagged_union.typelibID = (GUID)MSN_AUTH_GUID;
  707. QUERYCONTEXT qc;
  708. memset(&qc, 0, sizeof(qc));
  709. // fill in the minimum version number of the component you need
  710. //qc.dwVersionHi =
  711. //qc.dwVersionLo =
  712. hr = FaultInIEFeature(hWnd, &classpec, &qc, dwJITFlags);
  713. if (hr == S_OK)
  714. {
  715. hr = INET_E_AUTHENTICATION_REQUIRED;
  716. }
  717. else
  718. {
  719. hr = E_ABORT;
  720. }
  721. }
  722. break;
  723. #endif
  724. default:
  725. break;
  726. }
  727. }
  728. else if (HttpQueryInfo(_hRequest, HTTP_QUERY_STATUS_CODE, szBuffer,&cbLen, NULL))
  729. {
  730. dwStatus = atoi(szBuffer);
  731. _fProxyAuth = FALSE;
  732. switch (dwStatus)
  733. {
  734. case HTTP_STATUS_DENIED:
  735. {
  736. _hrINet = INET_E_AUTHENTICATION_REQUIRED;
  737. TransitState(INetState_AUTHENTICATE, TRUE);
  738. hr = E_PENDING;
  739. }
  740. break;
  741. case HTTP_STATUS_PROXY_AUTH_REQ :
  742. {
  743. _hrINet = INET_E_AUTHENTICATION_REQUIRED;
  744. TransitState(INetState_AUTHENTICATE, TRUE);
  745. _fProxyAuth = TRUE;
  746. hr = E_PENDING;
  747. }
  748. break;
  749. case HTTP_STATUS_MOVED:
  750. case HTTP_STATUS_REDIRECT:
  751. case HTTP_STATUS_REDIRECT_METHOD:
  752. case HTTP_STATUS_REDIRECT_KEEP_VERB:
  753. {
  754. cbLen = cbBufferLen;
  755. hr = RedirectRequest(szBuffer, &cbLen, dwStatus);
  756. if ((hr != S_FALSE) && (hr != NOERROR) && (hr != E_PENDING))
  757. {
  758. _hrError = INET_E_INVALID_URL;
  759. }
  760. else
  761. {
  762. _hrError = INET_E_OK;
  763. hr = S_FALSE;
  764. SetINetState(INetState_DONE);
  765. }
  766. }
  767. break;
  768. case HTTP_STATUS_NO_CONTENT:
  769. {
  770. BINDINFO *pBndInfo = GetBindInfo();
  771. if (pBndInfo && pBndInfo->dwBindVerb != BINDVERB_CUSTOM)
  772. {
  773. hr = _hrError = E_ABORT;
  774. SetBindResult(ERROR_CANCELLED, hr);
  775. }
  776. else
  777. {
  778. hr = QueryStatusOnResponseDefault(dwStatus);
  779. }
  780. }
  781. break;
  782. default:
  783. {
  784. hr = QueryStatusOnResponseDefault(dwStatus);
  785. }
  786. break;
  787. }
  788. }
  789. if (_hrError != INET_E_OK)
  790. {
  791. SetINetState(INetState_DONE);
  792. }
  793. PerfDbgLog1(tagCINetHttp, this, "-CINetHttp::QueryStatusOnResponse (hr:%lx)", hr);
  794. DEBUG_LEAVE(hr);
  795. return hr;
  796. }
  797. //+---------------------------------------------------------------------------
  798. //
  799. // Method: CINetHttp::QueryStatusOnResponseDefault
  800. //
  801. // Synopsis:
  802. //
  803. // Arguments: (none)
  804. //
  805. // Returns:
  806. //
  807. // History: 2-06-96 JohannP (Johann Posch) Created
  808. //
  809. // Notes:
  810. //
  811. //----------------------------------------------------------------------------
  812. HRESULT CINetHttp::QueryStatusOnResponseDefault(DWORD dwStat)
  813. {
  814. DEBUG_ENTER((DBG_APP,
  815. Hresult,
  816. "CINetHttp::QueryStatusOnResponseDefault",
  817. "this=%#x, %#x",
  818. this, dwStat
  819. ));
  820. PerfDbgLog(tagCINetHttp, this, "+CINetHttp::QueryStatusOnResponseDefault");
  821. HRESULT hr = NOERROR;
  822. DWORD dwStatus = 0;
  823. char szBuffer[max(2 * MAX_URL_SIZE, 400)];
  824. DWORD cbBufferLen = sizeof(szBuffer);
  825. DWORD cbLen = cbBufferLen;
  826. if( !dwStat )
  827. {
  828. if (HttpQueryInfo(_hRequest, HTTP_QUERY_STATUS_CODE, szBuffer,&cbLen, NULL))
  829. {
  830. dwStatus = atoi(szBuffer);
  831. }
  832. }
  833. else
  834. {
  835. dwStatus = dwStat;
  836. }
  837. if( dwStatus )
  838. {
  839. #if DBG==1
  840. if ( !((dwStatus >= HTTP_STATUS_OK) && (dwStatus <= HTTP_STATUS_GATEWAY_TIMEOUT)) )
  841. {
  842. DbgLog1(DEB_PROT|DEB_TRACE, this, "CINetHttp::QueryStatusOnResponse (dwStatus:%lx)", dwStatus);
  843. }
  844. PProtAssert(( (dwStatus >= HTTP_STATUS_BEGIN) && (dwStatus <= HTTP_STATUS_END)
  845. && L"WinINet returned an invalid status code: please contact a WININET developer" ));
  846. #endif //DBG==1
  847. // check if we got redirected from a file to a directory
  848. {
  849. cbLen = cbBufferLen;
  850. InternetQueryOption(_hRequest, INTERNET_OPTION_URL, szBuffer, &cbLen);
  851. if (cbLen)
  852. {
  853. BOOL fRedirected;
  854. fRedirected = strcmp(szBuffer, _pszFullURL);
  855. if (fRedirected)
  856. {
  857. cbLen = cbBufferLen;
  858. hr = RedirectRequest(szBuffer, &cbLen, dwStatus);
  859. if ((hr != NOERROR) && (hr != E_PENDING))
  860. {
  861. if (hr != INET_E_DOWNLOAD_FAILURE)
  862. {
  863. _hrError = INET_E_INVALID_URL;
  864. }
  865. // else set nothing
  866. }
  867. else
  868. {
  869. _hrError = INET_E_OK;
  870. }
  871. }
  872. }
  873. }
  874. cbLen = cbBufferLen;
  875. BOOL fRet = HttpQueryInfo(_hRequest, HTTP_QUERY_RAW_HEADERS_CRLF, szBuffer,&cbLen, NULL);
  876. BOOL fDeleteBuffer = FALSE;
  877. LPSTR lpszBuffer;
  878. if (!fRet)
  879. {
  880. DWORD dwError = GetLastError();
  881. if (dwError == ERROR_INSUFFICIENT_BUFFER)
  882. {
  883. lpszBuffer = new char[cbLen];
  884. if (!lpszBuffer)
  885. {
  886. hr = E_OUTOFMEMORY;
  887. goto End;
  888. }
  889. fDeleteBuffer = TRUE;
  890. fRet = HttpQueryInfo(_hRequest, HTTP_QUERY_RAW_HEADERS_CRLF, lpszBuffer, &cbLen, NULL);
  891. }
  892. }
  893. else
  894. lpszBuffer = szBuffer;
  895. if (fRet)
  896. {
  897. if (IsStatusOk(dwStatus))
  898. {
  899. hr = HttpNegOnHeadersAvailable(dwStatus, lpszBuffer);
  900. }
  901. else
  902. {
  903. hr = ErrorHandlingRequest(dwStatus, lpszBuffer);
  904. if ((hr != NOERROR) && (hr != E_PENDING))
  905. {
  906. _hrError = hr;
  907. }
  908. else
  909. {
  910. _hrError = INET_E_OK;
  911. }
  912. }
  913. if (hr == E_ABORT)
  914. {
  915. SetBindResult(ERROR_CANCELLED,hr);
  916. }
  917. }
  918. if (fDeleteBuffer)
  919. delete lpszBuffer;
  920. }
  921. End:
  922. PerfDbgLog1(tagCINetHttp, this, "-CINetHttp::QueryStatusOnResponseDefault (hr:%lx)", hr);
  923. DEBUG_LEAVE(hr);
  924. return hr;
  925. }
  926. //+---------------------------------------------------------------------------
  927. //
  928. // Method: CINetHttp::QueryHeaderOnResponse
  929. //
  930. // Synopsis:
  931. //
  932. // Arguments: (none)
  933. //
  934. // Returns:
  935. //
  936. // History: 2-06-96 JohannP (Johann Posch) Created
  937. //
  938. // Notes:
  939. //
  940. //----------------------------------------------------------------------------
  941. HRESULT CINetHttp::QueryHeaderOnResponse()
  942. {
  943. DEBUG_ENTER((DBG_APP,
  944. Hresult,
  945. "CINetHttp::QueryHeaderOnResponse",
  946. "this=%#x",
  947. this
  948. ));
  949. PerfDbgLog(tagCINetHttp, this, "+CINetHttp::QueryHeaderOnResponse");
  950. HRESULT hr = NOERROR;
  951. DWORD dwStatus;
  952. char szBuffer[max(2 * MAX_URL_SIZE, 400)];
  953. DWORD cbBufferLen = sizeof(szBuffer);
  954. DWORD dwFlags;
  955. char szMIMEType[SZMIMESIZE_MAX] = "";
  956. char szENCType[SZMIMESIZE_MAX] = "";
  957. BOOL fContentDisp = FALSE;
  958. // Get file length
  959. if(HttpQueryInfo(_hRequest, HTTP_QUERY_CONTENT_LENGTH, szBuffer,&cbBufferLen, NULL))
  960. {
  961. _cbDataSize = atoi(szBuffer);
  962. }
  963. // Get Content-Disposition
  964. szBuffer[0] = '\0';
  965. cbBufferLen = sizeof(szBuffer);
  966. if(HttpQueryInfo(
  967. _hRequest,
  968. HTTP_QUERY_CONTENT_DISPOSITION,
  969. szBuffer,
  970. &cbBufferLen,
  971. NULL) )
  972. {
  973. // Search for :Attachment, if found, report it
  974. if( StrStrI(szBuffer, vszAttachment) )
  975. {
  976. char szName[MAX_PATH];
  977. char *pName = NULL;
  978. // propogate the filename if available
  979. if( StrStrI(szBuffer, vszFileName) )
  980. {
  981. DWORD cbNameLen;
  982. szName[0] = '\0';
  983. cbNameLen = sizeof(szName);
  984. if(InternetQueryOption(_hRequest, INTERNET_OPTION_DATAFILE_NAME, szName, &cbNameLen))
  985. pName = PathFindFileName(szName);
  986. }
  987. ReportNotification(BINDSTATUS_CONTENTDISPOSITIONATTACH, (pName?pName:NULL));
  988. }
  989. if( StrStrI(szBuffer, vszFileName) )
  990. {
  991. fContentDisp = TRUE;
  992. }
  993. }
  994. // Get Accept-Ranges
  995. szBuffer[0] = '\0';
  996. cbBufferLen = sizeof(szBuffer);
  997. if(HttpQueryInfo(
  998. _hRequest,
  999. HTTP_QUERY_ACCEPT_RANGES,
  1000. szBuffer,
  1001. &cbBufferLen,
  1002. NULL) )
  1003. {
  1004. ReportNotification(BINDSTATUS_ACCEPTRANGES, NULL);
  1005. }
  1006. // mimetype
  1007. cbBufferLen = sizeof(szMIMEType);
  1008. szMIMEType[0] = 0;
  1009. HttpQueryInfo(_hRequest, HTTP_QUERY_CONTENT_TYPE, szMIMEType, &cbBufferLen, NULL);
  1010. if (cbBufferLen && (szMIMEType[0] != 0))
  1011. {
  1012. //BUG-WORK
  1013. //_pCTransData->SetMimeType(szMIMEType);
  1014. //_pCTrans->ReportProgress();
  1015. DbgLog1(DEB_PROT|DEB_TRACE, this,
  1016. "CINetHttp::QueryHeaderOnResponse MIME TYPE(szMime:%s)!",
  1017. szMIMEType);
  1018. // work around image display problem, turn off report mime type
  1019. // for direct binding
  1020. if( _grfBindF & BINDF_FROMURLMON)
  1021. {
  1022. ReportNotification(BINDSTATUS_MIMETYPEAVAILABLE,szMIMEType);
  1023. }
  1024. else
  1025. {
  1026. ReportNotification(BINDSTATUS_RAWMIMETYPE, szMIMEType);
  1027. }
  1028. /*** enable this block after wininet data sniff checked in ****
  1029. if( _cbDataSize )
  1030. {
  1031. // datasniff enabled ?
  1032. DWORD dwDataSniff = 0;
  1033. DWORD dwSize = sizeof(DWORD);
  1034. if( InternetQueryOption(
  1035. _hRequest,
  1036. INTERNET_OPTION_DATASNIFF,
  1037. &dwDataSniff,
  1038. &dwSize ) )
  1039. {
  1040. char szVCType[SZMIMESIZE_MAX] = "";
  1041. cbBufferLen = SZMIMESIZE_MAX;
  1042. InternetQueryOption(
  1043. _hRequest,
  1044. INTERNET_OPTION_VERIFIED_CONTENT_TYPE,
  1045. szVCType,
  1046. &cbBufferLen );
  1047. }
  1048. }
  1049. ****************************************************************/
  1050. }
  1051. else
  1052. {
  1053. DbgLog1(DEB_PROT|DEB_TRACE, this,
  1054. "CINetHttp::QueryHeaderOnResponse NO MIME TYPE (szUrl:%s)!",
  1055. GetBaseURL());
  1056. //BUGBUG: need data sniffing later on
  1057. //_pCTransData->SetMimeType("text/html");
  1058. // work around image display problem, turn off report mime type
  1059. // for direct binding
  1060. if( _grfBindF & BINDF_FROMURLMON)
  1061. {
  1062. ReportNotification(BINDSTATUS_MIMETYPEAVAILABLE,"text/html");
  1063. }
  1064. }
  1065. // content encoding
  1066. cbBufferLen = sizeof(szENCType);
  1067. HttpQueryInfo(_hRequest, HTTP_QUERY_CONTENT_ENCODING, szENCType, &cbBufferLen, NULL);
  1068. if (cbBufferLen && (szENCType[0] != 0))
  1069. {
  1070. DbgLog1(DEB_PROT|DEB_TRACE, this,
  1071. "CINetHttp::QueryHeaderOnResponse ENCODING TYPE(szEnc :%s)!",
  1072. szENCType);
  1073. //
  1074. // existing http servers may mishandle the content-encoding
  1075. // header, we have to taken care of the following cases:
  1076. //
  1077. // 1. we do not send Accept-Encoding header(http1.1 disabled),
  1078. // however, server sends back Content-Encoding: foo
  1079. // (_pszHeaders contains the accept-encoding info, so if
  1080. // this is null, we should not invoke the decoder )
  1081. //
  1082. // 2. we send Accept-Encoding: A, server sends back
  1083. // Content-Encoding: B, this is a protocol violation
  1084. // IgnoreContentEncoding() takes care of that, it compares
  1085. // the _pszHeader and szENCType, and we should not invoke
  1086. // the decoder if they are mis-matched
  1087. //
  1088. // 3. server sends out content-encoding, but what they really
  1089. // mean is that let the application (e.g. gunzip.exe) to
  1090. // handle the compressed file, we can add the check for
  1091. // content-type, for a list of content-type we do not
  1092. // understand (e.g. application/x-compress, x-world/x-vrml..)
  1093. // do not invoke the decoder
  1094. //
  1095. // Wininet changes http version if http1.1 over proxy is disabled.
  1096. // This happens only after httpSendRequest is called, which is when
  1097. // Urlmon might have passed in the Accept-Encoding headers.
  1098. // If we did pass in the headers, we need to make sure that they
  1099. // were not stripped out because wininet finally used Http 1.0.
  1100. if( _pszHeader && !RequestUsedHttp10(_hRequest) &&
  1101. !IgnoreContentEncoding(szMIMEType, szENCType, _pszHeader) )
  1102. {
  1103. ReportNotification(BINDSTATUS_ENCODING, szENCType);
  1104. // Load The decompression handler now...
  1105. COInetSession *pCOInetSession = NULL;
  1106. IOInetProtocol *pProtHandler = NULL;
  1107. IOInetProtocolSink *pProtSnkHandler = NULL;
  1108. IOInetBindInfo *pBindInfo = NULL;
  1109. LPWSTR pwzStr = DupA2W(szENCType);
  1110. CLSID clsid;
  1111. hr = GetCOInetSession(0,&pCOInetSession,0);
  1112. if( hr == NOERROR )
  1113. {
  1114. hr = pCOInetSession->CreateHandler(
  1115. pwzStr, 0, 0, &pProtHandler, &clsid);
  1116. if( hr == NOERROR )
  1117. {
  1118. hr = pProtHandler->QueryInterface(
  1119. IID_IOInetProtocolSink, (void **) &pProtSnkHandler);
  1120. //hr = QueryInterface(
  1121. // IID_IOInetBindInfo, (void **) &pBindInfo);
  1122. }
  1123. if( hr == NOERROR )
  1124. {
  1125. HRESULT hr2 = NOERROR;
  1126. hr2 = _pEmbdFilter->SwitchSink(pProtSnkHandler);
  1127. if( hr2 == NOERROR )
  1128. {
  1129. hr = _pEmbdFilter->StackFilter(
  1130. pwzStr, pProtHandler, pProtSnkHandler, _pOIBindInfo );
  1131. }
  1132. }
  1133. if( pBindInfo )
  1134. {
  1135. pBindInfo->Release();
  1136. }
  1137. }
  1138. if( szMIMEType[0] != '\0' )
  1139. {
  1140. ReportNotification(BINDSTATUS_MIMETYPEAVAILABLE,szMIMEType);
  1141. }
  1142. // Get Cache-Control
  1143. szBuffer[0] = '\0';
  1144. cbBufferLen = sizeof(szBuffer);
  1145. if(HttpQueryInfo(
  1146. _hRequest,
  1147. HTTP_QUERY_CACHE_CONTROL,
  1148. szBuffer,
  1149. &cbBufferLen,
  1150. NULL) )
  1151. {
  1152. ReportNotification(BINDSTATUS_CACHECONTROL, szBuffer);
  1153. }
  1154. if(fContentDisp)
  1155. {
  1156. // Get Content-Disposition
  1157. szBuffer[0] = '\0';
  1158. cbBufferLen = sizeof(szBuffer);
  1159. if(InternetQueryOption(_hRequest, INTERNET_OPTION_DATAFILE_NAME, szBuffer, &cbBufferLen))
  1160. {
  1161. ReportNotification(BINDSTATUS_CONTENTDISPOSITIONATTACH, PathFindFileName(szBuffer));
  1162. }
  1163. }
  1164. // urlmon will create a decompressed cache-file, so we should not
  1165. // report the compressed file name to the client.
  1166. _fFilenameReported = TRUE;
  1167. if (pwzStr)
  1168. {
  1169. delete pwzStr;
  1170. }
  1171. }
  1172. }
  1173. #ifdef TEST_STACK_FILTER_ONE
  1174. //test for stackable filter..
  1175. //need to include mft.hxx for sample implementation of the filter
  1176. {
  1177. IOInetProtocol* pFilter = (IOInetProtocol*) new CMft;
  1178. IOInetProtocolSink* pFilterSink = NULL;
  1179. pFilter->QueryInterface(
  1180. IID_IOInetProtocolSink, (void**)&pFilterSink);
  1181. // connect the last filter sink with pFilter's Sink
  1182. HRESULT hr2 = NOERROR;
  1183. hr2 = _pEmbdFilter->SwitchSink(pFilterSink);
  1184. if( hr2 == NOERROR )
  1185. {
  1186. hr = _pEmbdFilter->StackFilter(NULL, pFilter, NULL, NULL);
  1187. }
  1188. // this object gets created here, pFilter gets AddRef'd during
  1189. // the StackFilter(), we should release the additional Ref Count
  1190. // here
  1191. // this does not apply to the first filter stacked
  1192. if( _pEmbdFilter->FilterStacked() > 1 )
  1193. {
  1194. pFilter->Release();
  1195. }
  1196. }
  1197. #endif
  1198. #ifdef TEST_STACK_FILTER_TWO
  1199. {
  1200. // another one...
  1201. IOInetProtocol* pFilter_2 = (IOInetProtocol*) new CMft;
  1202. IOInetProtocolSink* pFilterSink_2 = NULL;
  1203. pFilter_2->QueryInterface(
  1204. IID_IOInetProtocolSink, (void**)&pFilterSink_2);
  1205. // connect the last filter sink with pFilter's Sink
  1206. HRESULT hr3 = NOERROR;
  1207. hr3 = _pEmbdFilter->SwitchSink(pFilterSink_2);
  1208. if( hr3 == NOERROR )
  1209. {
  1210. hr = _pEmbdFilter->StackFilter(NULL, pFilter_2, NULL, NULL);
  1211. }
  1212. // this object gets created here, pFilter gets AddRef'd during
  1213. // the StackFilter(), we should release the additional Ref Count
  1214. // here
  1215. // this does not apply to the first filter stacked
  1216. if( _pEmbdFilter->FilterStacked() > 1 )
  1217. {
  1218. pFilter_2->Release();
  1219. }
  1220. }
  1221. #endif
  1222. if (_hrError != INET_E_OK)
  1223. {
  1224. SetINetState(INetState_DONE);
  1225. hr = S_FALSE;
  1226. }
  1227. PerfDbgLog2(tagCINetHttp, this, "-CINetHttp::QueryHeaderOnResponse (hr:%lx, _cbDataSize:%ld)", hr, _cbDataSize);
  1228. DEBUG_LEAVE(hr);
  1229. return hr;
  1230. }
  1231. //+---------------------------------------------------------------------------
  1232. //
  1233. // Method: CINetHttp::RedirectRequest
  1234. //
  1235. // Synopsis:
  1236. //
  1237. // Arguments: [lpszBuffer] --
  1238. // [pdwBuffSize] --
  1239. //
  1240. // Returns:
  1241. //
  1242. // History: 2-06-96 JohannP (Johann Posch) Created
  1243. //
  1244. // Notes:
  1245. //
  1246. //----------------------------------------------------------------------------
  1247. HRESULT CINetHttp::RedirectRequest(LPSTR lpszBuffer, DWORD *pdwBuffSize, DWORD dwStatus)
  1248. {
  1249. DEBUG_ENTER((DBG_APP,
  1250. Hresult,
  1251. "CINetHttp::RedirectRequest",
  1252. "this=%#x, %#x, %#x, %d",
  1253. this, lpszBuffer, pdwBuffSize, dwStatus
  1254. ));
  1255. PerfDbgLog(tagCINetHttp, this, "+CINetHttp::RedirectRequest");
  1256. HRESULT hr = INET_E_DOWNLOAD_FAILURE;
  1257. char *pszHeader;
  1258. DWORD cbBufferLen;
  1259. BOOL fDeleteBuffer = FALSE;
  1260. BOOL fRet = FALSE;
  1261. // we assume when we get here that we have recieved a redirection
  1262. // now we are going to see where we need to do the next send
  1263. cbBufferLen = *pdwBuffSize;
  1264. if (cbBufferLen <= strlen(vszLocationTag))
  1265. {
  1266. goto End;
  1267. }
  1268. strcpy(lpszBuffer, vszLocationTag);
  1269. fRet = HttpQueryInfo(_hRequest, HTTP_QUERY_RAW_HEADERS, lpszBuffer,&cbBufferLen, NULL);
  1270. if (!fRet)
  1271. {
  1272. DWORD dwError = GetLastError();
  1273. if (dwError == ERROR_INSUFFICIENT_BUFFER)
  1274. {
  1275. lpszBuffer = new char[cbBufferLen];
  1276. if (!lpszBuffer)
  1277. {
  1278. hr = E_OUTOFMEMORY;
  1279. goto End;
  1280. }
  1281. fDeleteBuffer = TRUE;
  1282. fRet = HttpQueryInfo(_hRequest, HTTP_QUERY_RAW_HEADERS, lpszBuffer, &cbBufferLen, NULL);
  1283. dwError = GetLastError();
  1284. }
  1285. }
  1286. if (fRet)
  1287. {
  1288. LPSTR pszRedirect = 0;
  1289. pszHeader = FindTagInHeader(lpszBuffer, vszLocationTag);
  1290. if (!pszHeader)
  1291. {
  1292. goto End;
  1293. }
  1294. //Bug 21294: 204 responses sometimes have Location: headers, which may not mean redirects.
  1295. //To prevent a bogus redirection message, ensure that the comparison with wininet's url
  1296. //is made after stripping username and password from the original url, since wininet returns
  1297. //the url without these.
  1298. //Don't make this check if it's one of the 3** or username/password not in url.
  1299. if ((dwStatus < HTTP_STATUS_AMBIGUOUS) &&
  1300. (_pszUserName[0] || _pszPassword[0]))
  1301. {
  1302. CHAR* szUrlmonUrl = new CHAR[INTERNET_MAX_URL_LENGTH];
  1303. CHAR* szWininetUrl = new CHAR[INTERNET_MAX_URL_LENGTH];
  1304. DWORD dwUrlmonSize = INTERNET_MAX_URL_LENGTH;
  1305. DWORD dwWininetSize = INTERNET_MAX_URL_LENGTH;
  1306. BOOL bIdentical = FALSE;
  1307. URL_COMPONENTS url;
  1308. if (!szUrlmonUrl || !szWininetUrl)
  1309. goto deleteUrls;
  1310. memset(&url, 0, sizeof(URL_COMPONENTS));
  1311. url.dwStructSize = sizeof(url);
  1312. url.lpszScheme = _pszProtocol;
  1313. url.lpszHostName = _pszServerName;
  1314. url.lpszUrlPath = _pszObject;
  1315. url.nPort = _ipPort;
  1316. if (InternetCreateUrl(&url, 0, szUrlmonUrl, &dwUrlmonSize) &&
  1317. InternetQueryOption(_hRequest, INTERNET_OPTION_URL, szWininetUrl, &dwWininetSize))
  1318. {
  1319. if ((dwUrlmonSize == dwWininetSize)
  1320. && !strcmp(szUrlmonUrl, szWininetUrl))
  1321. {
  1322. bIdentical = TRUE;
  1323. }
  1324. DEBUG_ENTER((DBG_APP,
  1325. Bool,
  1326. "CINetHttp::RedirectRequestComparison",
  1327. "this=%#x, %.80q, %d, %.80q, %d",
  1328. this, szUrlmonUrl, dwUrlmonSize, szWininetUrl, dwWininetSize
  1329. ));
  1330. DEBUG_LEAVE(bIdentical);
  1331. }
  1332. deleteUrls:
  1333. if (szUrlmonUrl)
  1334. delete [] szUrlmonUrl;
  1335. if (szWininetUrl)
  1336. delete [] szWininetUrl;
  1337. if (bIdentical)
  1338. goto End;
  1339. }
  1340. if (dwStatus < HTTP_STATUS_AMBIGUOUS)
  1341. {
  1342. //Bug 33662: Location: headers are only allowed to be absolute URIs
  1343. //check for relative URI and, if found, pretend doesn't exist for 2** status codes.
  1344. char* pszHostname = new char[MAX_URL_SIZE];
  1345. DWORD dwHostname = MAX_URL_SIZE;
  1346. HRESULT hrTemp;
  1347. if (!pszHostname)
  1348. {
  1349. hr = E_OUTOFMEMORY;
  1350. goto End;
  1351. }
  1352. hrTemp = UrlGetPartA(pszHeader + strlen(vszLocationTag), pszHostname, &dwHostname, URL_PART_HOSTNAME, 0);
  1353. delete [] pszHostname;
  1354. if (FAILED(hrTemp))
  1355. {
  1356. //this is a relative URI since hostname couldn't be found.
  1357. //hr remains INET_E_DOWNLOAD_FAILURE
  1358. goto End;
  1359. }
  1360. }
  1361. //
  1362. // _pszPartURL get allocated here!
  1363. //
  1364. if( _pszPartURL )
  1365. {
  1366. delete [] _pszPartURL;
  1367. _pszPartURL = NULL;
  1368. }
  1369. DWORD dwPartUrlLen = strlen( (pszHeader + strlen(vszLocationTag) ) );
  1370. if( dwPartUrlLen > MAX_URL_SIZE)
  1371. {
  1372. hr = INET_E_DOWNLOAD_FAILURE;
  1373. goto End;
  1374. }
  1375. _pszPartURL = new char[dwPartUrlLen + 1];
  1376. if( !_pszPartURL )
  1377. {
  1378. hr = E_OUTOFMEMORY;
  1379. goto End;
  1380. }
  1381. strcpy(_pszPartURL, pszHeader + strlen(vszLocationTag));
  1382. DbgLog1(DEB_PROT|DEB_TRACE, this, "=== CINetHttp::RedirectRequest (Location:%s)", _pszPartURL);
  1383. _fRedirected = TRUE;
  1384. hr = S_FALSE;
  1385. if (!ParseUrl())
  1386. {
  1387. pszRedirect = _pszPartURL;
  1388. }
  1389. else
  1390. {
  1391. pszRedirect = _pszFullURL;
  1392. }
  1393. PProtAssert((pszRedirect));
  1394. ReportResultAndStop(INET_E_REDIRECTING, 0, 0, DupA2W(pszRedirect));
  1395. }
  1396. End:
  1397. if (fDeleteBuffer)
  1398. delete lpszBuffer;
  1399. PerfDbgLog1(tagCINetHttp, this, "-CINetHttp::RedirectRequest(hr:%lx)", hr);
  1400. DEBUG_LEAVE(hr);
  1401. return hr;
  1402. }
  1403. //+---------------------------------------------------------------------------
  1404. //
  1405. // Method: CINetHttp::ErrorHandlingRequest
  1406. //
  1407. // Synopsis:
  1408. //
  1409. // Arguments: [dwstatus] --
  1410. // [szBuffer] --
  1411. //
  1412. // Returns:
  1413. //
  1414. // History: 2-28-96 JohannP (Johann Posch) Created
  1415. //
  1416. // Notes:
  1417. //
  1418. //----------------------------------------------------------------------------
  1419. HRESULT CINetHttp::ErrorHandlingRequest(DWORD dwStatus, LPSTR szBuffer)
  1420. {
  1421. DEBUG_ENTER((DBG_APP,
  1422. Hresult,
  1423. "CINetHttp::ErrorHandlingRequest",
  1424. "this=%#x, %#x, %.80q",
  1425. this, dwStatus, szBuffer
  1426. ));
  1427. PerfDbgLog1(tagCINetHttp, this, "+CINetHttp::ErrorHandlingRequest (dwStatus:%ld)", dwStatus);
  1428. HRESULT hr = NOERROR;
  1429. PProtAssert((szBuffer));
  1430. hr = HttpNegOnError(dwStatus,szBuffer);
  1431. if (hr == E_RETRY)
  1432. {
  1433. _hrINet = NOERROR;
  1434. hr = INetAsyncSendRequest();
  1435. }
  1436. else if (hr == E_ABORT)
  1437. {
  1438. _hrINet = E_ABORT;
  1439. }
  1440. else if (hr == S_FALSE)
  1441. {
  1442. // the error was not handled - stop download
  1443. _hrINet = hr = HResultFromHttpStatus(dwStatus);
  1444. }
  1445. else
  1446. {
  1447. _hrINet = hr;
  1448. }
  1449. PerfDbgLog1(tagCINetHttp, this, "-CINetHttp::ErrorHandlingRequest(hr:%lx)", hr);
  1450. DEBUG_LEAVE(hr);
  1451. return hr;
  1452. }
  1453. //+---------------------------------------------------------------------------
  1454. //
  1455. // Method: CINetHttp::GetVerb
  1456. //
  1457. // Synopsis:
  1458. //
  1459. // Arguments: (none)
  1460. //
  1461. // Returns:
  1462. //
  1463. // History: 2-05-96 JohannP (Johann Posch) Created
  1464. //
  1465. // Notes:
  1466. //
  1467. //----------------------------------------------------------------------------
  1468. LPSTR CINetHttp::GetVerb()
  1469. {
  1470. DEBUG_ENTER((DBG_APP,
  1471. String,
  1472. "CINetHttp::GetVerb",
  1473. "this=%#x",
  1474. this
  1475. ));
  1476. PerfDbgLog(tagCINetHttp, this, "+CINetHttp::GetVerb");
  1477. LPSTR pszRes = vszGet;
  1478. if (_fRedirected == TRUE)
  1479. {
  1480. // for HTTP 1.1, we have to check if this is an POST->POST redirect
  1481. INTERNET_VERSION_INFO httpVersion;
  1482. DWORD dwBufferSize = sizeof(INTERNET_VERSION_INFO);
  1483. if( InternetQueryOption( _hRequest, INTERNET_OPTION_HTTP_VERSION, &httpVersion, &dwBufferSize )
  1484. && httpVersion.dwMajorVersion >= 1
  1485. && httpVersion.dwMinorVersion >= 1 )
  1486. {
  1487. CHAR szVerb[16];
  1488. DWORD dwIndex;
  1489. DWORD dwLength = sizeof(szVerb);
  1490. if( HttpQueryInfo(_hRequest, HTTP_QUERY_REQUEST_METHOD, szVerb, &dwLength, &dwIndex)
  1491. && !lstrcmp(szVerb, vszPost) )
  1492. {
  1493. // HACK HACK HACK !!
  1494. // Double check the status code to see if this is a real POST
  1495. // there is a HttpQueryInfo() bug which will send verb=POST
  1496. // on a POST->GET Redirect
  1497. //
  1498. DWORD dwStatus = 0;
  1499. if ( HttpQueryInfo(
  1500. _hRequest,
  1501. HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER,
  1502. &dwStatus ,&dwLength, NULL)
  1503. && dwStatus == HTTP_STATUS_REDIRECT_KEEP_VERB )
  1504. {
  1505. _fP2PRedirected = TRUE;
  1506. pszRes = vszPost;
  1507. }
  1508. }
  1509. }
  1510. }
  1511. else
  1512. {
  1513. BINDINFO *pBndInfo = GetBindInfo();
  1514. if (pBndInfo)
  1515. {
  1516. switch (pBndInfo->dwBindVerb)
  1517. {
  1518. case BINDVERB_GET :
  1519. pszRes = vszGet;
  1520. break;
  1521. case BINDVERB_POST :
  1522. pszRes = vszPost;
  1523. break;
  1524. case BINDVERB_PUT :
  1525. pszRes = vszPut;
  1526. break;
  1527. case BINDVERB_CUSTOM :
  1528. {
  1529. //BUGBUG: custom verb support
  1530. if (!_pszVerb && pBndInfo->szCustomVerb)
  1531. {
  1532. pszRes = _pszVerb = DupW2A(pBndInfo->szCustomVerb);
  1533. }
  1534. else if(_pszVerb)
  1535. {
  1536. pszRes = _pszVerb;
  1537. }
  1538. }
  1539. break;
  1540. }
  1541. }
  1542. }
  1543. PerfDbgLog1(tagCINetHttp, this, "-CINetHttp::GetVerb (szRes:%s)", pszRes);
  1544. DEBUG_LEAVE(pszRes);
  1545. return pszRes;
  1546. }
  1547. //+---------------------------------------------------------------------------
  1548. //
  1549. // Method: CINetHttp::GetAdditionalHeader
  1550. //
  1551. // Synopsis:
  1552. //
  1553. // Arguments: [ppszRes] --
  1554. // [pdwSize] --
  1555. //
  1556. // Returns:
  1557. //
  1558. // History: 2-05-96 JohannP (Johann Posch) Created
  1559. //
  1560. // Notes:
  1561. //
  1562. //----------------------------------------------------------------------------
  1563. HRESULT CINetHttp::GetAdditionalHeader()
  1564. {
  1565. DEBUG_ENTER((DBG_APP,
  1566. Hresult,
  1567. "CINetHttp::GetAdditionalHeader",
  1568. "this=%#x",
  1569. this
  1570. ));
  1571. PerfDbgLog(tagCINetHttp, this, "+CINetHttp::GetAdditionalHeader");
  1572. DWORD dwSizeData = 0;
  1573. DWORD dwSizeHeader = 0;
  1574. LPSTR szLocal;
  1575. szLocal = g_pszUAInfoString;
  1576. dwSizeHeader += strlen(szLocal);
  1577. ULONG dwSizeEncHeader = 0;
  1578. PProtAssert((_pOIBindInfo));
  1579. // only send Accept-Encoding header with HTTP 1.1 or higher
  1580. INTERNET_VERSION_INFO httpVersion;
  1581. DWORD dwBufferSize = sizeof(INTERNET_VERSION_INFO);
  1582. if( _hRequest
  1583. && _pOIBindInfo
  1584. && InternetQueryOption( _hRequest, INTERNET_OPTION_HTTP_VERSION, &httpVersion, &dwBufferSize )
  1585. && httpVersion.dwMajorVersion >= 1
  1586. && httpVersion.dwMinorVersion >= 1 )
  1587. {
  1588. dwSizeEncHeader = 1;
  1589. dwSizeHeader += strlen(gszAcceptEncHeaders);
  1590. }
  1591. // delete the old header and allocate a new buffer
  1592. if (_pszHeader)
  1593. {
  1594. delete _pszHeader;
  1595. _pszHeader = 0;
  1596. }
  1597. if (dwSizeHeader || dwSizeEncHeader)
  1598. {
  1599. _pszHeader = new CHAR [dwSizeHeader + 1];
  1600. }
  1601. if (_pszHeader)
  1602. {
  1603. if (szLocal && szLocal[0] != 0)
  1604. {
  1605. strcat(_pszHeader, szLocal);
  1606. }
  1607. if( dwSizeEncHeader)
  1608. {
  1609. strcat(_pszHeader, gszAcceptEncHeaders);
  1610. }
  1611. }
  1612. PerfDbgLog2(tagCINetHttp, this, "-CINetHttp::GetAdditionalHeader (pStr:>%s<, hr:%lx)", XDBG(_pszHeader,""), NOERROR);
  1613. DEBUG_LEAVE(NOERROR);
  1614. return NOERROR;
  1615. }
  1616. //+---------------------------------------------------------------------------
  1617. //
  1618. // Method: CINetHttp::GetDataToSend
  1619. //
  1620. // Synopsis:
  1621. //
  1622. // Arguments: [ppBuffer] --
  1623. // [pdwSize] --
  1624. //
  1625. // Returns:
  1626. //
  1627. // History: 2-05-96 JohannP (Johann Posch) Created
  1628. //
  1629. // Notes:
  1630. //
  1631. //----------------------------------------------------------------------------
  1632. HRESULT CINetHttp::GetDataToSend(LPVOID *ppBuffer, DWORD *pdwSize)
  1633. {
  1634. DEBUG_ENTER((DBG_APP,
  1635. Hresult,
  1636. "CINetHttp::GetDataToSend",
  1637. "this=%#x, %#x, %#x",
  1638. this, ppBuffer, pdwSize
  1639. ));
  1640. HRESULT hr = INET_E_DOWNLOAD_FAILURE;
  1641. PerfDbgLog(tagCINetHttp, this, "+CINetHttp::GetDataToSend");
  1642. *ppBuffer = NULL;
  1643. *pdwSize = 0;
  1644. BINDINFO *pBndInfo = GetBindInfo();
  1645. if (pBndInfo)
  1646. {
  1647. switch (pBndInfo->dwBindVerb)
  1648. {
  1649. default:
  1650. case BINDVERB_CUSTOM :
  1651. case BINDVERB_POST :
  1652. case BINDVERB_PUT :
  1653. {
  1654. if (pBndInfo->stgmedData.tymed == TYMED_HGLOBAL)
  1655. {
  1656. *ppBuffer = pBndInfo->stgmedData.hGlobal;
  1657. *pdwSize = pBndInfo->cbstgmedData;
  1658. hr = NOERROR;
  1659. }
  1660. }
  1661. break;
  1662. case BINDVERB_GET :
  1663. // nothing should be uploaded
  1664. break;
  1665. }
  1666. }
  1667. PerfDbgLog3(tagCINetHttp, this, "-CINetHttp::GetDataToSend (pBuffer:%lx, dwSize:%ld, hr:%lx)", *ppBuffer, *pdwSize, hr);
  1668. DEBUG_LEAVE(hr);
  1669. return hr;
  1670. }
  1671. HRESULT CINetHttp::HttpNegGetRootSecurityId()
  1672. {
  1673. HRESULT hr = NOERROR;
  1674. BYTE bRootSID[MAX_SIZE_SECURITY_ID];
  1675. if (_pbRootSecurityId == NULL)
  1676. {
  1677. if (_pHttpNeg2 == NULL)
  1678. {
  1679. /*
  1680. if (_pHttpNeg == NULL)
  1681. hr = QueryService(IID_IHttpNegotiate, (void **) &_pHttpNeg);
  1682. if (!_pHttpNeg || (hr != NOERROR))
  1683. goto End;
  1684. */
  1685. hr = QueryService(IID_IHttpNegotiate2, (void **) &_pHttpNeg2);
  1686. if (!_pHttpNeg2)
  1687. {
  1688. _pbRootSecurityId = INVALID_P_ROOT_SECURITY_ID;
  1689. goto End;
  1690. }
  1691. }
  1692. _cbRootSecurityId = MAX_SIZE_SECURITY_ID;
  1693. hr = _pHttpNeg2->GetRootSecurityId( bRootSID, &_cbRootSecurityId, 0 );
  1694. if (FAILED(hr))
  1695. {
  1696. _pbRootSecurityId = INVALID_P_ROOT_SECURITY_ID;
  1697. goto End;
  1698. }
  1699. if (_cbRootSecurityId <= 0)
  1700. goto End;
  1701. _pbRootSecurityId = new BYTE[_cbRootSecurityId];
  1702. if (!_pbRootSecurityId)
  1703. goto End;
  1704. memcpy (_pbRootSecurityId, bRootSID, _cbRootSecurityId);
  1705. }
  1706. End:
  1707. return hr;
  1708. }
  1709. //+---------------------------------------------------------------------------
  1710. //
  1711. // Method: CINetHttp::HttpNegBeginningTransaction
  1712. //
  1713. // Synopsis:
  1714. //
  1715. // Arguments: [szURL] --
  1716. // [DWORD] --
  1717. // [dwReserved] --
  1718. // [pszAdditionalHeaders] --
  1719. //
  1720. // Returns:
  1721. //
  1722. // History: 2-08-96 JohannP (Johann Posch) Created
  1723. //
  1724. // Notes:
  1725. //
  1726. //----------------------------------------------------------------------------
  1727. HRESULT CINetHttp::HttpNegBeginningTransaction()
  1728. {
  1729. DEBUG_ENTER((DBG_APP,
  1730. Hresult,
  1731. "CINetHttp::HttpNegBeginningTransaction",
  1732. "this=%#x",
  1733. this
  1734. ));
  1735. PerfDbgLog(tagCINetHttp, this, "+CINetHttp::HttpNegBeginningTransaction");
  1736. HRESULT hr = NOERROR;
  1737. LPWSTR pwzAddHeaders = NULL;
  1738. if (_pHttpNeg == NULL)
  1739. {
  1740. hr = QueryService(IID_IHttpNegotiate, (void **) &_pHttpNeg);
  1741. }
  1742. if (_pHttpNeg && (hr == NOERROR))
  1743. {
  1744. LPWSTR pwzUrl = GetUrl();
  1745. LPWSTR pwzHeaders = NULL;
  1746. DWORD dwlen = 0;
  1747. if (_pszHeader)
  1748. {
  1749. dwlen = strlen(_pszHeader);
  1750. pwzHeaders = new WCHAR [dwlen +1];
  1751. if (pwzHeaders == NULL)
  1752. {
  1753. hr = E_OUTOFMEMORY;
  1754. goto End;
  1755. }
  1756. A2W(_pszHeader, pwzHeaders,dwlen + 1);
  1757. }
  1758. PProtAssert((pwzUrl));
  1759. hr = _pHttpNeg->BeginningTransaction(pwzUrl, pwzHeaders, NULL, &pwzAddHeaders);
  1760. if (SUCCEEDED(hr) )
  1761. {
  1762. if (pwzAddHeaders)
  1763. {
  1764. // add the additional length
  1765. dwlen += wcslen(pwzAddHeaders) * sizeof(WCHAR);
  1766. }
  1767. if (dwlen)
  1768. {
  1769. if (_pszSendHeader)
  1770. {
  1771. if (strlen(_pszSendHeader) < (dwlen + 1))
  1772. {
  1773. // delete the old header
  1774. delete _pszSendHeader;
  1775. // allocate a new one
  1776. _pszSendHeader = new CHAR [dwlen + 1];
  1777. }
  1778. }
  1779. else
  1780. {
  1781. _pszSendHeader = new CHAR [dwlen + 1];
  1782. }
  1783. if (_pszSendHeader)
  1784. {
  1785. if ( pwzAddHeaders )
  1786. {
  1787. W2A(pwzAddHeaders, _pszSendHeader, dwlen + 1);
  1788. // append the original header
  1789. if (_pszHeader)
  1790. {
  1791. strcat(_pszSendHeader,_pszHeader);
  1792. }
  1793. }
  1794. else
  1795. {
  1796. // no additional header
  1797. strcpy(_pszSendHeader, _pszHeader);
  1798. }
  1799. }
  1800. else
  1801. {
  1802. hr = E_OUTOFMEMORY;
  1803. }
  1804. // delete the wchar header
  1805. if (pwzHeaders)
  1806. {
  1807. delete pwzHeaders;
  1808. }
  1809. }
  1810. }
  1811. }
  1812. else
  1813. {
  1814. PProtAssert((_pHttpNeg == NULL));
  1815. }
  1816. End:
  1817. // delete this buffer
  1818. if (pwzAddHeaders)
  1819. {
  1820. delete pwzAddHeaders;
  1821. }
  1822. PerfDbgLog(tagCINetHttp, this, "-CINetHttp::HttpNegBeginningTransaction");
  1823. DEBUG_LEAVE(hr);
  1824. return hr;
  1825. }
  1826. //+---------------------------------------------------------------------------
  1827. //
  1828. // Method: CINetHttp::HttpNegOnHeadersAvailable
  1829. //
  1830. // Synopsis:
  1831. //
  1832. // Arguments: [dwResponseCode] --
  1833. // [szHeaders] --
  1834. //
  1835. // Returns:
  1836. //
  1837. // History: 2-08-96 JohannP (Johann Posch) Created
  1838. //
  1839. // Notes:
  1840. //
  1841. //----------------------------------------------------------------------------
  1842. HRESULT CINetHttp::HttpNegOnHeadersAvailable(DWORD dwResponseCode, LPSTR szResponseHeader)
  1843. {
  1844. DEBUG_ENTER((DBG_APP,
  1845. Hresult,
  1846. "CINetHttp::HttpNegOnHeadersAvailable",
  1847. "this=%#x, %#x, %.80q",
  1848. this, dwResponseCode, szResponseHeader
  1849. ));
  1850. PerfDbgLog2(tagCINetHttp, this, "+CINetHttp::HttpNegOnHeadersAvailable (dwResponseCode:%lx) (szResponseHeader:%s)", dwResponseCode, XDBG(szResponseHeader,""));
  1851. HRESULT hr = NOERROR;
  1852. PProtAssert((szResponseHeader != NULL));
  1853. if (_pHttpNeg)
  1854. {
  1855. LPWSTR pwzResponseHeader;
  1856. DWORD dwlen = strlen(szResponseHeader);
  1857. pwzResponseHeader = new WCHAR [dwlen +1];
  1858. if (pwzResponseHeader == NULL)
  1859. {
  1860. hr = E_OUTOFMEMORY;
  1861. }
  1862. else
  1863. {
  1864. PProtAssert((pwzResponseHeader));
  1865. A2W(szResponseHeader, pwzResponseHeader, dwlen + 1);
  1866. if( _pHttpNeg )
  1867. {
  1868. hr = _pHttpNeg->OnResponse(dwResponseCode, pwzResponseHeader,NULL ,NULL);
  1869. }
  1870. // the only valid return code is NOERROR
  1871. PProtAssert((hr == NOERROR && "HttpNegotiate::OnHeaders returned ivalid hresult"));
  1872. PProtAssert((pwzResponseHeader));
  1873. delete pwzResponseHeader;
  1874. }
  1875. }
  1876. PerfDbgLog1(tagCINetHttp, this, "-CINetHttp::HttpNegOnHeadersAvailable (hr:%lx)", hr);
  1877. DEBUG_LEAVE(hr);
  1878. return hr;
  1879. }
  1880. //+---------------------------------------------------------------------------
  1881. //
  1882. // Method: CINetHttp::HttpNegOnError
  1883. //
  1884. // Synopsis:
  1885. //
  1886. // Arguments: [dwResponseCode] --
  1887. // [szResponseHeaders] --
  1888. // [pszAdditionalRequestHeaders] --
  1889. //
  1890. // Returns:
  1891. //
  1892. // History: 2-08-96 JohannP (Johann Posch) Created
  1893. //
  1894. // Notes: return S_FALSE as default - will stop download
  1895. // and map to INET_E hresult
  1896. //----------------------------------------------------------------------------
  1897. HRESULT CINetHttp::HttpNegOnError(DWORD dwResponseCode, LPSTR szResponseHeader)
  1898. {
  1899. DEBUG_ENTER((DBG_APP,
  1900. Hresult,
  1901. "CINetHttp::HttpNegOnError",
  1902. "this=%#x, %#x, %.80q",
  1903. this, dwResponseCode, szResponseHeader
  1904. ));
  1905. PerfDbgLog(tagCINetHttp, this, "+CINetHttp::HttpNegOnError");
  1906. HRESULT hr = S_FALSE;
  1907. PProtAssert((szResponseHeader != NULL));
  1908. if (_pHttpNeg)
  1909. {
  1910. LPWSTR pwzNewSendHeader = 0;
  1911. LPWSTR pwzSendHeader = 0;
  1912. LPWSTR pwzResponseHeader = 0;
  1913. DWORD dwLenSendHeader = 0;
  1914. DWORD dwLenResponseHeader = 0;
  1915. if (_pszSendHeader)
  1916. {
  1917. dwLenSendHeader = strlen(_pszSendHeader);
  1918. pwzSendHeader = new WCHAR [dwLenSendHeader + 1];
  1919. }
  1920. if (pwzSendHeader)
  1921. {
  1922. A2W(_pszSendHeader, pwzSendHeader, dwLenSendHeader + 1);
  1923. }
  1924. if (szResponseHeader)
  1925. {
  1926. dwLenResponseHeader = strlen(szResponseHeader);
  1927. pwzResponseHeader = new WCHAR [dwLenResponseHeader + 1];
  1928. }
  1929. if (pwzResponseHeader)
  1930. {
  1931. A2W(szResponseHeader, pwzResponseHeader, dwLenResponseHeader + 1);
  1932. }
  1933. if( _pHttpNeg )
  1934. {
  1935. hr = _pHttpNeg->OnResponse(dwResponseCode, pwzResponseHeader,pwzSendHeader ,&pwzNewSendHeader);
  1936. }
  1937. if (pwzSendHeader)
  1938. {
  1939. delete pwzSendHeader;
  1940. pwzSendHeader = 0;
  1941. }
  1942. if (pwzResponseHeader)
  1943. {
  1944. delete pwzResponseHeader;
  1945. pwzResponseHeader = 0;
  1946. }
  1947. if ((hr == NOERROR) && (pwzNewSendHeader != NULL))
  1948. {
  1949. LPSTR pszNewSendHeader = 0;
  1950. DWORD dwLen = wcslen(pwzNewSendHeader);
  1951. DWORD dwLen1 = 0;
  1952. if (_pszSendHeader)
  1953. {
  1954. dwLen1 = strlen(_pszSendHeader);
  1955. PProtAssert((dwLen + dwLen1));
  1956. pszNewSendHeader = new CHAR [dwLen + dwLen1 + 1];
  1957. if (pszNewSendHeader)
  1958. {
  1959. strcpy(pszNewSendHeader, _pszSendHeader);
  1960. W2A(pwzNewSendHeader,pszNewSendHeader + dwLen1, dwLen + 1);
  1961. // retry the call
  1962. hr = E_RETRY;
  1963. }
  1964. else
  1965. {
  1966. hr = E_OUTOFMEMORY;
  1967. }
  1968. }
  1969. else
  1970. {
  1971. hr = S_FALSE;
  1972. }
  1973. }
  1974. else
  1975. {
  1976. // we should not have headers
  1977. PProtAssert((pwzNewSendHeader == NULL));
  1978. if (pwzNewSendHeader)
  1979. {
  1980. delete pwzNewSendHeader;
  1981. }
  1982. }
  1983. }
  1984. else
  1985. {
  1986. // the error should be mapped to an INET_E hresult
  1987. hr = S_FALSE;
  1988. }
  1989. PerfDbgLog1(tagCINetHttp, this, "-CINetHttp::HttpNegOnError (hr:%lx)", hr);
  1990. DEBUG_LEAVE(hr);
  1991. return hr;
  1992. }
  1993. //+---------------------------------------------------------------------------
  1994. //
  1995. // Method: CINet::SecurityProblem
  1996. //
  1997. // Synopsis:
  1998. //
  1999. // Arguments: [lpszBuffer] --
  2000. // [pdwBuffSize] --
  2001. //
  2002. // Returns:
  2003. //
  2004. // History: 2-06-96 JohannP (Johann Posch) Created
  2005. //
  2006. // Notes:
  2007. //
  2008. //----------------------------------------------------------------------------
  2009. HRESULT CINetHttp::HttpSecurity(DWORD dwProblem)
  2010. {
  2011. DEBUG_ENTER((DBG_APP,
  2012. Hresult,
  2013. "CINetHttp::HttpSecurity",
  2014. "this=%#x, %#x",
  2015. this, dwProblem
  2016. ));
  2017. PerfDbgLog(tagCINetHttp, this, "+CINetHttp::HttpSecurity");
  2018. HRESULT hr = NOERROR;
  2019. HWND hwnd;
  2020. hr = HttpSecurityProblem(&hwnd, dwProblem);
  2021. if (hr == NOERROR)
  2022. {
  2023. if (hwnd)
  2024. {
  2025. DWORD dwBindF = GetBindFlags();
  2026. DWORD dwFlags = (FLAGS_ERROR_UI_FLAGS_CHANGE_OPTIONS | FLAGS_ERROR_UI_FLAGS_GENERATE_DATA );
  2027. if ((dwBindF & BINDF_NO_UI) || (dwBindF & BINDF_SILENTOPERATION))
  2028. {
  2029. dwFlags |= FLAGS_ERROR_UI_FLAGS_NO_UI;
  2030. }
  2031. DWORD dwError;
  2032. if (SUCCEEDED(ZonesSecurityCheck(hwnd, dwProblem, &dwError)))
  2033. {
  2034. // dwError will be set by ZonesSecurityCheck.
  2035. }
  2036. else
  2037. {
  2038. dwError = InternetErrorDlg(hwnd, _hRequest, dwProblem, dwFlags,NULL);
  2039. }
  2040. switch (dwError)
  2041. {
  2042. case ERROR_CANCELLED :
  2043. _hrINet = hr = E_ABORT;
  2044. break;
  2045. case ERROR_SUCCESS :
  2046. _hrINet = hr = E_RETRY;
  2047. break;
  2048. default:
  2049. _hrINet = hr = E_ABORT;
  2050. break;
  2051. }
  2052. }
  2053. else
  2054. {
  2055. hr = INET_E_SECURITY_PROBLEM;
  2056. }
  2057. }
  2058. else if (hr == E_ABORT)
  2059. {
  2060. _hrINet = E_ABORT;
  2061. }
  2062. if (hr == E_RETRY)
  2063. {
  2064. _hrINet = NOERROR;
  2065. hr = INetAsyncSendRequest();
  2066. }
  2067. else if (hr == E_ABORT)
  2068. {
  2069. _hrINet = E_ABORT;
  2070. }
  2071. else if (hr != NOERROR )
  2072. {
  2073. // set the error to access denied
  2074. _hrINet = hr = INET_E_SECURITY_PROBLEM;
  2075. }
  2076. PerfDbgLog1(tagCINetHttp, this, "-CINetHttp::HttpSecurity(hr:%lx)", hr);
  2077. DEBUG_LEAVE(hr);
  2078. return hr;
  2079. }
  2080. //+---------------------------------------------------------------------------
  2081. //
  2082. // Method: CINet::ZonesSecurityCheck
  2083. //
  2084. // Synopsis:
  2085. //
  2086. // Arguments: [hwnd] --
  2087. // [dwProblem] --
  2088. // [pdwError] --
  2089. //
  2090. // Returns: SUCCESS if it was able to decide the action, INET_E_DEFAULT_ACTION otherwise.
  2091. //
  2092. // History: 8-14-97 JohannP (Johann Posch) Created
  2093. //
  2094. // Notes:
  2095. //
  2096. //----------------------------------------------------------------------------
  2097. HRESULT CINetHttp::ZonesSecurityCheck(HWND hWnd, DWORD dwProblem, DWORD *pdwError)
  2098. {
  2099. DEBUG_ENTER((DBG_APP,
  2100. Hresult,
  2101. "CINetHttp::ZonesSecurityCheck",
  2102. "this=%#x, %#x, %#x, %#x",
  2103. this, hWnd, dwProblem, pdwError
  2104. ));
  2105. PerfDbgLog(tagCINetHttp, this, "+CINetHttp::HttpSecurity");
  2106. HRESULT hr = INET_E_DEFAULT_ACTION;
  2107. if (pdwError == NULL)
  2108. {
  2109. TransAssert(FALSE);
  2110. DEBUG_LEAVE(E_INVALIDARG);
  2111. return E_INVALIDARG;
  2112. }
  2113. // Right now the only error we check for is the redirect confirmation error.
  2114. if (dwProblem == ERROR_HTTP_REDIRECT_NEEDS_CONFIRMATION ||
  2115. dwProblem == ERROR_INTERNET_HTTPS_HTTP_SUBMIT_REDIR)
  2116. {
  2117. IInternetSecurityManager *pSecMgr = NULL;
  2118. if (SUCCEEDED(CoCreateInstance(CLSID_InternetSecurityManager, NULL,
  2119. CLSCTX_INPROC_SERVER, IID_IInternetSecurityManager, (void **)&pSecMgr)))
  2120. {
  2121. char szUrl[MAX_URL_SIZE];
  2122. WCHAR wzUrl[MAX_URL_SIZE];
  2123. DWORD cbLen = MAX_URL_SIZE;
  2124. DWORD dwPolicy;
  2125. TransAssert(pSecMgr != NULL);
  2126. InternetQueryOption(_hRequest, INTERNET_OPTION_URL, szUrl, &cbLen);
  2127. // First check if the redirect is to the same server. If that is the
  2128. // case we don't need to warn because we already did the first time around.
  2129. if (dwProblem == ERROR_HTTP_REDIRECT_NEEDS_CONFIRMATION)
  2130. {
  2131. URL_COMPONENTS uc = { 0 };
  2132. uc.dwStructSize = sizeof(uc);
  2133. uc.dwHostNameLength = 1; // So we get back the host name.
  2134. if ( InternetCrackUrl(szUrl, 0, 0, &uc) &&
  2135. (StrCmpNI(uc.lpszHostName, GetServerName(), uc.dwHostNameLength) == 0)
  2136. )
  2137. {
  2138. *pdwError = ERROR_SUCCESS;
  2139. hr = S_OK;
  2140. }
  2141. }
  2142. if (hr == INET_E_DEFAULT_ACTION)
  2143. {
  2144. // Convert to widechar so we can call the security manager.
  2145. MultiByteToWideChar(CP_ACP, 0, szUrl, -1, wzUrl, MAX_URL_SIZE);
  2146. PARSEDURL pu;
  2147. pu.cbSize = sizeof(pu);
  2148. DWORD dwPUAflags = (GetBindFlags() & BINDF_ENFORCERESTRICTED) ? PUAF_ENFORCERESTRICTED : 0;
  2149. if (SUCCEEDED(ParseURLA(szUrl, &pu)) && pu.nScheme == URL_SCHEME_HTTPS)
  2150. {
  2151. // The forms submit zones policies are only supposed to apply to
  2152. // unencrypted posts. We will allow these to be posted silently.
  2153. *pdwError = ERROR_SUCCESS;
  2154. hr = S_OK ;
  2155. }
  2156. else if (SUCCEEDED(pSecMgr->ProcessUrlAction(wzUrl, URLACTION_HTML_SUBMIT_FORMS_TO,
  2157. (BYTE *)&dwPolicy, sizeof(dwPolicy), NULL, 0, dwPUAflags | PUAF_NOUI, 0)))
  2158. {
  2159. DWORD dwPermissions = GetUrlPolicyPermissions(dwPolicy);
  2160. // If it is allow or deny don't call InternetErrorDlg, unless it is a encrypted to
  2161. // unencrypted redir in which case we still need to warn the user..
  2162. if (dwPermissions == URLPOLICY_ALLOW && dwProblem != ERROR_INTERNET_HTTPS_HTTP_SUBMIT_REDIR)
  2163. {
  2164. *pdwError = ERROR_SUCCESS;
  2165. hr = S_OK;
  2166. }
  2167. else if (dwPermissions == URLPOLICY_DISALLOW)
  2168. {
  2169. *pdwError = ERROR_CANCELLED;
  2170. hr = S_OK;
  2171. }
  2172. }
  2173. }
  2174. pSecMgr->Release();
  2175. }
  2176. }
  2177. PerfDbgLog1(tagCINetHttp, this, "-CINetHttp::ZonesSecurityCheck(hr:%lx)", hr);
  2178. DEBUG_LEAVE(hr);
  2179. return hr;
  2180. }
  2181. //+---------------------------------------------------------------------------
  2182. //
  2183. // Method: CINetHttp::HttpSecurityProblem
  2184. //
  2185. // Synopsis: QI's for HttpSecurity or IWindow
  2186. //
  2187. // Arguments: [phwnd] -- window handle for security dialog
  2188. //
  2189. // Returns: S_OK if dialog should be displayed
  2190. //
  2191. // History: 2-08-96 JohannP (Johann Posch) Created
  2192. //
  2193. // Notes:
  2194. //
  2195. //----------------------------------------------------------------------------
  2196. HRESULT CINetHttp::HttpSecurityProblem(HWND* phwnd, DWORD dwProblem)
  2197. {
  2198. DEBUG_ENTER((DBG_APP,
  2199. Hresult,
  2200. "CINetHttp::HttpSecurityProblem",
  2201. "this=%#x, %#x, %#x",
  2202. this, phwnd, dwProblem
  2203. ));
  2204. PerfDbgLog(tagCINetHttp, this, "+CINetHttp::HttpSecurityProblem");
  2205. HRESULT hr = NOERROR;
  2206. *phwnd = 0;
  2207. if (_pHttSecurity == NULL)
  2208. {
  2209. hr = QueryService(IID_IHttpSecurity, (void **) &_pHttSecurity);
  2210. }
  2211. if ((hr == NOERROR) && _pHttSecurity)
  2212. {
  2213. hr = _pHttSecurity->OnSecurityProblem(dwProblem);
  2214. if (hr == S_OK)
  2215. {
  2216. // client wants to continue
  2217. }
  2218. else if (hr == S_FALSE)
  2219. {
  2220. // client does not care
  2221. hr = _pHttSecurity->GetWindow(IID_IHttpSecurity, phwnd);
  2222. UrlMkAssert(( ((hr == S_FALSE) && (*phwnd == NULL))
  2223. || ((hr == NOERROR) && (*phwnd != NULL)) ));
  2224. }
  2225. else if (hr != E_ABORT)
  2226. {
  2227. UrlMkAssert((FALSE && "Invalid result on IHttSecurity->OnSecurityProblem"));
  2228. }
  2229. }
  2230. else
  2231. {
  2232. if (_pWindow == NULL)
  2233. {
  2234. hr = QueryService(IID_IWindowForBindingUI, (void **) &_pWindow);
  2235. }
  2236. else
  2237. hr = NOERROR; //We need to reset this hr, since we cached _pWindow
  2238. if ((hr == NOERROR) && _pWindow)
  2239. {
  2240. hr = _pWindow->GetWindow(IID_IHttpSecurity, phwnd);
  2241. UrlMkAssert(( (hr == S_FALSE) && (*phwnd == NULL)
  2242. || (hr == S_OK) && (*phwnd != NULL)));
  2243. }
  2244. }
  2245. PerfDbgLog2(tagCINetHttp, this, "-CINetHttp::HttpSecurityProblem (hr:%lx, hwnd:%lx)", hr, *phwnd);
  2246. DEBUG_LEAVE(hr);
  2247. return hr;
  2248. }
  2249. //+---------------------------------------------------------------------------
  2250. //
  2251. // Method: CINetHttp::HResultFromInternetError
  2252. //
  2253. // Synopsis:
  2254. //
  2255. // Arguments: [dwStatus] --
  2256. //
  2257. // Returns:
  2258. //
  2259. // History: 3-22-96 JohannP (Johann Posch) Created
  2260. //
  2261. // Notes:
  2262. //
  2263. //----------------------------------------------------------------------------
  2264. HRESULT CINetHttp::HResultFromHttpStatus(DWORD dwStatus)
  2265. {
  2266. DEBUG_ENTER((DBG_APP,
  2267. Hresult,
  2268. "CINetHttp::HResultFromHttpStatus",
  2269. "this=%#x, %#x",
  2270. this, dwStatus
  2271. ));
  2272. PerfDbgLog(tagCINetHttp, this, "+CINetHttp::HResultFromHttpStatus");
  2273. HRESULT hr = NOERROR;
  2274. switch(dwStatus)
  2275. {
  2276. case HTTP_STATUS_OK :
  2277. case HTTP_STATUS_NOT_MODIFIED :
  2278. case HTTP_STATUS_RETRY_WITH :
  2279. hr = NOERROR;
  2280. break;
  2281. case HTTP_STATUS_NOT_FOUND :
  2282. hr = INET_E_OBJECT_NOT_FOUND;
  2283. break;
  2284. case HTTP_STATUS_NONE_ACCEPTABLE :
  2285. // comes back if server can not handle mime type
  2286. hr = INET_E_NO_VALID_MEDIA;
  2287. break;
  2288. case HTTP_STATUS_SERVICE_UNAVAIL :
  2289. hr = INET_E_INVALID_REQUEST;
  2290. break;
  2291. case HTTP_STATUS_GATEWAY_TIMEOUT :
  2292. case HTTP_STATUS_REQUEST_TIMEOUT :
  2293. hr = INET_E_CONNECTION_TIMEOUT;
  2294. break;
  2295. case HTTP_STATUS_CREATED :
  2296. case HTTP_STATUS_ACCEPTED :
  2297. case HTTP_STATUS_PARTIAL :
  2298. case HTTP_STATUS_NO_CONTENT :
  2299. case HTTP_STATUS_AMBIGUOUS :
  2300. case HTTP_STATUS_MOVED :
  2301. case HTTP_STATUS_REDIRECT :
  2302. case HTTP_STATUS_REDIRECT_METHOD :
  2303. case HTTP_STATUS_REDIRECT_KEEP_VERB:
  2304. case HTTP_STATUS_BAD_REQUEST :
  2305. case HTTP_STATUS_DENIED :
  2306. case HTTP_STATUS_PAYMENT_REQ :
  2307. case HTTP_STATUS_FORBIDDEN :
  2308. case HTTP_STATUS_BAD_METHOD :
  2309. case HTTP_STATUS_PROXY_AUTH_REQ :
  2310. case HTTP_STATUS_CONFLICT :
  2311. case HTTP_STATUS_GONE :
  2312. case HTTP_STATUS_LENGTH_REQUIRED :
  2313. case HTTP_STATUS_SERVER_ERROR :
  2314. case HTTP_STATUS_NOT_SUPPORTED :
  2315. case HTTP_STATUS_BAD_GATEWAY :
  2316. default:
  2317. //PProtAssert((FALSE && "Mapping Ineternet error to generic hresult!"));
  2318. hr = INET_E_DOWNLOAD_FAILURE;
  2319. DbgLog2(DEB_PROT|DEB_TRACE, this, "=== Mapping Internet error to generic hresult!(dwStatus:%ld, hr:%lx)", dwStatus, hr);
  2320. break;
  2321. }
  2322. PerfDbgLog1(tagCINetHttp, this, "-CINetHttp::HResultFromHttpStatus (hr:%lx)", hr);
  2323. DEBUG_LEAVE(hr);
  2324. return hr;
  2325. }
  2326. //+---------------------------------------------------------------------------
  2327. //
  2328. // Method: CINetHttp::Terminate
  2329. //
  2330. // Synopsis: Close the server and request handle - wininet will make a
  2331. // callback on each handle closed
  2332. //
  2333. // Arguments: [dwOptions] --
  2334. //
  2335. // Returns:
  2336. //
  2337. // History: 07-27-96 JohannP (Johann Posch) Created
  2338. //
  2339. // Notes:
  2340. //
  2341. //----------------------------------------------------------------------------
  2342. STDMETHODIMP CINetHttp::Terminate(DWORD dwOptions)
  2343. {
  2344. DEBUG_ENTER((DBG_APP,
  2345. Hresult,
  2346. "CINetHttp::Terminate",
  2347. "this=%#x, %#x",
  2348. this, dwOptions
  2349. ));
  2350. PerfDbgLog(tagCINetHttp, this, "+CINetHttp::Terminate");
  2351. HRESULT hr = NOERROR;
  2352. //PProtAssert(( IsApartmentThread() ));
  2353. if (_pHttpNeg)
  2354. {
  2355. PerfDbgLog1(tagCINetHttp, this, "=== CINetHttp::Terminate Release on _pHttpNeg (%lx)", _pHttpNeg);
  2356. _pHttpNeg->Release();
  2357. _pHttpNeg = NULL;
  2358. }
  2359. if (_pHttpNeg2)
  2360. {
  2361. PerfDbgLog1(tagCINetHttp, this, "=== CINetHttp::Terminate Release on _pHttpNeg2 (%lx)", _pHttpNeg2);
  2362. _pHttpNeg2->Release();
  2363. _pHttpNeg2 = NULL;
  2364. }
  2365. if (_pWindow)
  2366. {
  2367. PerfDbgLog1(tagCINetHttp, this, "+CINetHttp::Terminate Release on _pWindow (%lx)", _pWindow);
  2368. _pWindow->Release();
  2369. _pWindow = NULL;
  2370. }
  2371. if (_pHttSecurity)
  2372. {
  2373. PerfDbgLog1(tagCINetHttp, this, "+CINetHttp::Terminate Release on _pHttSecurity (%lx)", _pHttSecurity);
  2374. _pHttSecurity->Release();
  2375. _pHttSecurity = NULL;
  2376. }
  2377. hr = CINet::Terminate(dwOptions);
  2378. PerfDbgLog1(tagCINetHttp, this, "-CINetHttp::Terminate (hr:%lx)", hr);
  2379. DEBUG_LEAVE(hr);
  2380. return hr;
  2381. }
  2382. //+---------------------------------------------------------------------------
  2383. //
  2384. // Method: CINetHttpS::CINetHttpS
  2385. //
  2386. // Synopsis:
  2387. //
  2388. // Arguments: (none)
  2389. //
  2390. // Returns:
  2391. //
  2392. // History: 2-06-96 JohannP (Johann Posch) Created
  2393. //
  2394. // Notes:
  2395. //
  2396. //----------------------------------------------------------------------------
  2397. CINetHttpS::CINetHttpS(REFCLSID rclsid, IUnknown *pUnkOuter) : CINetHttp(rclsid,pUnkOuter)
  2398. {
  2399. DEBUG_ENTER((DBG_APP,
  2400. None,
  2401. "CINetHttpS::CINetHttpS",
  2402. "this=%#x, %#x, %#x",
  2403. this, &rclsid, pUnkOuter
  2404. ));
  2405. PerfDbgLog(tagCINetHttp, this, "+CINetHttpS::CINetHttpS");
  2406. _dwIsA = DLD_PROTOCOL_HTTPS;
  2407. _dwConnectFlags = INTERNET_FLAG_SECURE;
  2408. _dwOpenFlags = INTERNET_FLAG_SECURE;
  2409. PerfDbgLog(tagCINetHttp, this, "-CINetHttpS::CINetHttpS");
  2410. DEBUG_LEAVE(0);
  2411. }
  2412. //+---------------------------------------------------------------------------
  2413. //
  2414. // Method: CINetHttpS::~CINetHttpS
  2415. //
  2416. // Synopsis:
  2417. //
  2418. // Arguments: (none)
  2419. //
  2420. // Returns:
  2421. //
  2422. // History: 2-06-96 JohannP (Johann Posch) Created
  2423. //
  2424. // Notes:
  2425. //
  2426. //----------------------------------------------------------------------------
  2427. CINetHttpS::~CINetHttpS()
  2428. {
  2429. DEBUG_ENTER((DBG_APP,
  2430. None,
  2431. "CINetHttpS::~CINetHttpS",
  2432. "this=%#x",
  2433. this
  2434. ));
  2435. PerfDbgLog(tagCINetHttp, this, "+CINetHttpS::~CINetHttpS");
  2436. PerfDbgLog(tagCINetHttp, this, "-CINetHttpS::~CINetHttpS");
  2437. DEBUG_LEAVE(0);
  2438. }
  2439. //+---------------------------------------------------------------------------
  2440. //
  2441. // Method: CINetHttp::INetWrite
  2442. //
  2443. // Synopsis:
  2444. //
  2445. // Arguments: (none)
  2446. //
  2447. // Returns:
  2448. //
  2449. // History: 1-27-96 JohannP (Johann Posch) Created
  2450. //
  2451. // Notes:
  2452. //
  2453. //----------------------------------------------------------------------------
  2454. HRESULT CINetHttp::INetWrite()
  2455. {
  2456. DEBUG_ENTER((DBG_APP,
  2457. Hresult,
  2458. "CINetHttp::INetWrite",
  2459. "this=%#x",
  2460. this
  2461. ));
  2462. TransDebugOut((DEB_PROT, "%p OUT CINetHttp::INetWrite\n", this));
  2463. HRESULT hr = NOERROR;
  2464. BOOL fRet;
  2465. DWORD dwSendFlags = HSR_CHUNKED | HSR_INITIATE;
  2466. DWORD dwSendContext = 0;
  2467. // If our caller gave us a TYMED_ISTREAM, then we need to pick it up
  2468. // now.
  2469. if (!_pStm)
  2470. {
  2471. BINDINFO *pBI = GetBindInfo();
  2472. if (pBI && pBI->stgmedData.tymed == TYMED_ISTREAM)
  2473. {
  2474. _pStm = pBI->stgmedData.pstm;
  2475. }
  2476. }
  2477. TransAssert((_pStm));
  2478. if( _fSendAgain && _pStm )
  2479. {
  2480. LARGE_INTEGER li;
  2481. li.LowPart = 0;
  2482. li.HighPart = 0;
  2483. hr = _pStm->Seek(li, STREAM_SEEK_SET, NULL);
  2484. if( SUCCEEDED(hr) )
  2485. {
  2486. _fSendEnd = FALSE;
  2487. }
  2488. else
  2489. {
  2490. _fCompleted = TRUE;
  2491. }
  2492. _fSendAgain = FALSE;
  2493. }
  2494. // loop until pending
  2495. if (_fSendEnd)
  2496. {
  2497. _hrError = INET_E_DONE;
  2498. }
  2499. else do
  2500. {
  2501. _dwBytesSent = 0;
  2502. SetStatePending(E_PENDING);
  2503. hr = GetNextSendBuffer(&_inetBufferSend,_pStm);
  2504. if (FAILED(hr))
  2505. {
  2506. break;
  2507. }
  2508. if (hr == S_FALSE)
  2509. {
  2510. // end of stream
  2511. _fCompleted = TRUE;
  2512. }
  2513. if (!_fCompleted)
  2514. {
  2515. if (_inetBufferSend.dwBufferLength)
  2516. {
  2517. fRet = InternetWriteFile(
  2518. _hRequest //IN HINTERNET hFile,
  2519. ,_inetBufferSend.lpvBuffer //IN LPCVOID lpBuffer,
  2520. ,_inetBufferSend.dwBufferLength //IN DWORD dwNumberOfBytesToWrite,
  2521. ,&_dwBytesSent //OUT LPDWORD lpdwNumberOfBytesWritten
  2522. );
  2523. }
  2524. else
  2525. {
  2526. fRet = TRUE;
  2527. }
  2528. }
  2529. else
  2530. {
  2531. fRet = HttpEndRequestA(
  2532. _hRequest //IN HINTERNET hRequest,
  2533. ,NULL
  2534. ,dwSendFlags //IN DWORD dwFlags,
  2535. ,dwSendContext //IN DWORD dwContext
  2536. );
  2537. _fSendEnd = TRUE;
  2538. }
  2539. //PerfDbgLog(tagCINetHttp, this, "-CINetHttp::INetAsyncSendRequest HttpSendRequest");
  2540. if (fRet == FALSE)
  2541. {
  2542. DWORD dwLstError = GetLastError();
  2543. if (dwLstError == ERROR_IO_PENDING)
  2544. {
  2545. // wait async for the handle
  2546. hr = E_PENDING;
  2547. }
  2548. else
  2549. {
  2550. SetStatePending(NOERROR);
  2551. hr = _hrError = INET_E_DOWNLOAD_FAILURE;
  2552. SetBindResult(dwLstError,hr);
  2553. //PerfDbgLog3(tagCINetHttp, this, "CINetHttp::INetAsyncSendRequest (fRet:%d, _hrError:%lx, LstError:%ld)", fRet, _hrError, dwLstError);
  2554. }
  2555. }
  2556. else
  2557. {
  2558. SetStatePending(NOERROR);
  2559. }
  2560. } while ((fRet == TRUE) && (_fCompleted == FALSE));
  2561. if (_hrError != INET_E_OK)
  2562. {
  2563. // we need to terminate here
  2564. ReportResultAndStop((_hrError == INET_E_DONE) ? NOERROR : _hrError);
  2565. }
  2566. TransDebugOut((DEB_PROT, "%p OUT CINetHttp::INetWrite (hr:%lx)\n", this, hr));
  2567. DEBUG_LEAVE(hr);
  2568. return hr;
  2569. }
  2570. //+---------------------------------------------------------------------------
  2571. //
  2572. // Method: CINetHttp::GetNextSendBuffer
  2573. //
  2574. // Synopsis:
  2575. //
  2576. // Arguments: [pIB] --
  2577. // [pStm] --
  2578. // [fFirst] --
  2579. //
  2580. // Returns:
  2581. //
  2582. // History: 4-28-1997 JohannP (Johann Posch) Created
  2583. //
  2584. // Notes:
  2585. //
  2586. //----------------------------------------------------------------------------
  2587. HRESULT CINetHttp::GetNextSendBuffer(INTERNET_BUFFERS *pIB, IStream *pStm, BOOL fFirst)
  2588. {
  2589. DEBUG_ENTER((DBG_APP,
  2590. Hresult,
  2591. "CINetHttp::GetNextSendBuffer",
  2592. "this=%#x, %#x, %#x, %B",
  2593. this, pIB, pStm, fFirst
  2594. ));
  2595. TransDebugOut((DEB_PROT, "%p OUT CINetHttp::GetNextSendBuffer\n", this));
  2596. HRESULT hr = NOERROR;
  2597. TransAssert(pIB);
  2598. do
  2599. {
  2600. BINDINFO *pBndInfo = GetBindInfo();
  2601. DWORD dwBufferFilled = 0;
  2602. if (!pStm)
  2603. {
  2604. hr = E_FAIL;
  2605. break;
  2606. }
  2607. if (!fFirst)
  2608. {
  2609. TransAssert((_pBuffer));
  2610. hr = pStm->Read(_pBuffer, _dwBufferSize, &dwBufferFilled);
  2611. if (FAILED(hr))
  2612. {
  2613. break;
  2614. }
  2615. else if (!dwBufferFilled)
  2616. {
  2617. hr = S_FALSE;
  2618. }
  2619. }
  2620. else
  2621. {
  2622. LARGE_INTEGER li;
  2623. li.LowPart = 0;
  2624. li.HighPart = 0;
  2625. // We do not need to addref this here
  2626. pStm->Seek(li, STREAM_SEEK_SET, NULL);
  2627. if( !_pBuffer )
  2628. {
  2629. _pBuffer = new char [SENDBUFFER_MAX];
  2630. if (!_pBuffer)
  2631. {
  2632. hr = E_OUTOFMEMORY;
  2633. break;
  2634. }
  2635. _dwBufferSize = SENDBUFFER_MAX;
  2636. }
  2637. }
  2638. pIB->dwStructSize = sizeof (INTERNET_BUFFERSA);
  2639. pIB->Next = 0;
  2640. pIB->lpcszHeader = (fFirst) ? _pszSendHeader : 0;
  2641. pIB->dwHeadersLength = (fFirst) ? ((_pszSendHeader) ? (ULONG)-1L : 0L) : 0;
  2642. pIB->dwHeadersTotal = (fFirst) ? ((_pszSendHeader) ? (ULONG)-1L : 0L) : 0;
  2643. pIB->lpvBuffer = (fFirst) ? 0 : _pBuffer;
  2644. pIB->dwBufferLength = (fFirst) ? 0 : dwBufferFilled;
  2645. pIB->dwBufferTotal = (fFirst) ? pBndInfo->cbstgmedData : 0; // :_dwBufferSize;
  2646. pIB->dwOffsetLow = 0;
  2647. pIB->dwOffsetHigh = 0;
  2648. break;
  2649. } while (TRUE);
  2650. TransDebugOut((DEB_PROT, "%p OUT CINetHttp::GetNextSendBuffer (hr:%lx)\n", this, hr));
  2651. DEBUG_LEAVE(hr);
  2652. return hr;
  2653. }