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.

7554 lines
218 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1995.
  5. //
  6. // File: cnet.cxx
  7. //
  8. // Contents:
  9. //
  10. // Classes:
  11. //
  12. // Functions:
  13. //
  14. // History: 12-04-95 JohannP (Johann Posch) Created
  15. //
  16. //----------------------------------------------------------------------------
  17. #include <iapp.h>
  18. #include <winineti.h> // contains bogus INTERNET_FLAG_NO_UI
  19. #include <shlwapip.h>
  20. CMutexSem g_mxsSession; // single access to InternetOpen
  21. PerfDbgTag(tagCINet, "Urlmon", "Log CINet", DEB_PROT);
  22. PerfDbgTag(tagCINetErr, "Urlmon", "Log CINet Errors", DEB_PROT|DEB_ERROR);
  23. LONG UrlMonInvokeExceptionFilter( DWORD lCode, LPEXCEPTION_POINTERS lpep );
  24. DWORD StrLenMultiByteWithMlang(LPCWSTR, DWORD);
  25. BOOL ConvertUnicodeUrl(LPCWSTR, LPSTR, INT, DWORD, BOOL, BOOL*);
  26. DWORD CountUnicodeToUtf8(LPCWSTR, DWORD, BOOL);
  27. extern BOOL g_bGlobalUTF8Enabled;
  28. #define INTERNET_POLICIES_KEY "SOFTWARE\\Policies\\Microsoft\\Windows\\CurrentVersion\\Internet Settings"
  29. typedef UINT (WINAPI *GetSystemWow64DirectoryPtr) (LPTSTR lpBuffer, UINT uSize);
  30. // Need this in GetUserAgentString.
  31. HRESULT CallRegInstall(LPSTR szSection);
  32. HRESULT EnsureSecurityManager ();
  33. class CInetState
  34. {
  35. enum WHAT_STATE
  36. {
  37. INETSTATE_NONE = 0
  38. ,INETSTATE_SET = 1
  39. ,INETSTATE_HANDLED = 2
  40. };
  41. public:
  42. void SetState(DWORD dwState)
  43. {
  44. DEBUG_ENTER((DBG_APP,
  45. None,
  46. "CInetState::SetState",
  47. "this=%#x, %#x",
  48. this, dwState
  49. ));
  50. CLock lck(_mxs);
  51. _dwState = dwState;
  52. _What = INETSTATE_SET;
  53. DEBUG_LEAVE(0);
  54. }
  55. HRESULT HandleState()
  56. {
  57. DEBUG_ENTER((DBG_APP,
  58. Hresult,
  59. "CInetState::HandleState",
  60. "this=%#x",
  61. this
  62. ));
  63. HRESULT hr = NOERROR;
  64. DWORD dwStateNow;
  65. BOOL fPropagate;
  66. {
  67. CLock lck(_mxs);
  68. dwStateNow = _dwState;
  69. fPropagate = (_What == INETSTATE_SET) ? TRUE : FALSE;
  70. _What = INETSTATE_HANDLED;
  71. }
  72. if (fPropagate)
  73. {
  74. hr = PropagateStateChange(dwStateNow);
  75. }
  76. DEBUG_LEAVE(hr);
  77. return hr;
  78. }
  79. HRESULT PropagateStateChange(DWORD dwState);
  80. CInetState()
  81. {
  82. DEBUG_ENTER((DBG_APP,
  83. None,
  84. "CInetState::CInetState",
  85. "this=%#x",
  86. this
  87. ));
  88. _dwState = 0;
  89. _What = INETSTATE_NONE;
  90. DEBUG_LEAVE(0);
  91. }
  92. ~CInetState()
  93. {
  94. DEBUG_ENTER((DBG_APP,
  95. None,
  96. "CInetState::~CInetState",
  97. "this=%#x",
  98. this
  99. ));
  100. DEBUG_LEAVE(0);
  101. }
  102. private:
  103. CMutexSem _mxs;
  104. DWORD _dwState;
  105. WHAT_STATE _What;
  106. };
  107. //+---------------------------------------------------------------------------
  108. //
  109. // Method: CInetState::PropagateStateChange
  110. //
  111. // Synopsis:
  112. //
  113. // Arguments: (none)
  114. //
  115. // Returns:
  116. //
  117. // History: 1-22-1997 JohannP (Johann Posch) Created
  118. //
  119. // Notes:
  120. //
  121. //----------------------------------------------------------------------------
  122. HRESULT CInetState::PropagateStateChange(DWORD dwWhat)
  123. {
  124. DEBUG_ENTER((DBG_APP,
  125. Hresult,
  126. "CInetState::PropagateStateChange",
  127. "this=%#x, %#x",
  128. this, dwWhat
  129. ));
  130. PerfDbgLog(tagCINet, this, "+CInetState::PropagateStateChange");
  131. HRESULT hr = NOERROR;
  132. // BUGBUG: IE5 need to implement these!
  133. #if 0
  134. if (dwWhat & INTERNET_STATE_CONNECTED)
  135. {
  136. NotfDeliverNotification(
  137. NOTIFICATIONTYPE_CONNECT_TO_INTERNET // REFNOTIFICATIONTYPE rNotificationType
  138. ,CLSID_PROCESS_BROADCAST // REFCLSID rClsidDest
  139. ,(DELIVERMODE)0 // DELIVERMODE deliverMode
  140. ,0 // DWORD dwReserved
  141. );
  142. }
  143. if (dwWhat & INTERNET_STATE_DISCONNECTED)
  144. {
  145. NotfDeliverNotification(
  146. NOTIFICATIONTYPE_DISCONNECT_FROM_INTERNET // REFNOTIFICATIONTYPE rNotificationType
  147. ,CLSID_PROCESS_BROADCAST // REFCLSID rClsidDest
  148. ,(DELIVERMODE)0 // DELIVERMODE deliverMode
  149. ,0 // DWORD dwReserved
  150. );
  151. }
  152. if (dwWhat & INTERNET_STATE_DISCONNECTED_BY_USER)
  153. {
  154. NotfDeliverNotification(
  155. NOTIFICATIONTYPE_CONFIG_CHANGED // REFNOTIFICATIONTYPE rNotificationType
  156. ,CLSID_PROCESS_BROADCAST // REFCLSID rClsidDest
  157. ,(DELIVERMODE)0 // DELIVERMODE deliverMode
  158. ,0 // DWORD dwReserved
  159. );
  160. }
  161. #ifdef _with_idle_and_busy_
  162. //
  163. // NOTE: wininet will send idle with every state change
  164. // will be fixed by RFirth
  165. if (dwWhat & INTERNET_STATE_IDLE)
  166. {
  167. NotfDeliverNotification(
  168. NOTIFICATIONTYPE_INET_IDLE // REFNOTIFICATIONTYPE rNotificationType
  169. ,CLSID_PROCESS_BROADCAST // REFCLSID rClsidDest
  170. ,(DELIVERMODE)0 // DELIVERMODE deliverMode
  171. ,0 // DWORD dwReserved
  172. );
  173. }
  174. if (dwWhat & INTERNET_STATE_BUSY)
  175. {
  176. NotfDeliverNotification(
  177. NOTIFICATIONTYPE_INET_BUSY // REFNOTIFICATIONTYPE rNotificationType
  178. ,CLSID_PROCESS_BROADCAST // REFCLSID rClsidDest
  179. ,(DELIVERMODE)0 // DELIVERMODE deliverMode
  180. ,0 // DWORD dwReserved
  181. );
  182. }
  183. #endif //_with_idle_and_busy_
  184. #endif // 0
  185. PerfDbgLog1(tagCINet, this, "-CInetState:PropagateStateChange (hr:%lx)", hr);
  186. DEBUG_LEAVE(hr);
  187. return hr;
  188. }
  189. //
  190. // REMOVE THIS joHANNP
  191. //
  192. extern LPSTR g_pszUserAgentString;
  193. HINTERNET g_hSession;
  194. CInetState g_cInetState;
  195. char vszLocationTag[] = "Location: ";
  196. static DWORD dwLstError;
  197. typedef struct tagProtocolInfo
  198. {
  199. LPWSTR pwzProtocol;
  200. LPSTR pszProtocol;
  201. DWORD dwId;
  202. CLSID *pClsID;
  203. int protlen;
  204. } ProtocolInfo;
  205. extern IInternetSecurityManager* g_pSecurityManager; // to handle GetSecurityId for cookies fix.
  206. /*
  207. This function is not heavy on error-checking:
  208. The ASSERTS in the code MUST be satisfied for this function to work
  209. NOTE: don't care about OPAQUE urls since they are NOT http by definition.
  210. */
  211. enum ComparisonState
  212. {
  213. seenZone=1,
  214. seen1Dot,
  215. seen2Dots,
  216. seen3Dots,
  217. domainSame
  218. };
  219. #define MAKELOWER(val) (((val) > 'a') ? (val) : ((val)-'A'+'a'))
  220. BOOL IsKnown2ndSubstring(BYTE* pStart, BYTE* pEnd)
  221. {
  222. static const char *s_pachSpecialDomains[] = {"COM", "EDU", "NET", "ORG", "GOV", "MIL", "INT"};
  223. static const DWORD s_padwSpecialDomains[] = {0x00636f6d, 0x00656475, 0x006e6574, 0x006f7267, 0x00676f76, 0x006d696c, 0x00696e74};
  224. BOOL bKnown = FALSE;
  225. int nLen = (int) (pEnd-pStart+1);
  226. if ((nLen==2) && !StrCmpNI((LPCSTR)pStart, "CO", nLen))
  227. {
  228. bKnown = TRUE;
  229. }
  230. else if (nLen==3)
  231. {
  232. DWORD dwExt, dwByte;
  233. dwByte = *pStart++;
  234. dwExt = MAKELOWER(dwByte);
  235. dwExt <<= 8;
  236. dwByte = *pStart++;
  237. dwExt |= MAKELOWER(dwByte);
  238. dwExt <<= 8;
  239. dwByte = *pStart++;
  240. dwExt |= MAKELOWER(dwByte);
  241. for (int i=0; i<sizeof(s_padwSpecialDomains);)
  242. {
  243. if (dwExt == s_padwSpecialDomains[i++])
  244. {
  245. bKnown = TRUE;
  246. break;
  247. }
  248. }
  249. }
  250. return bKnown;
  251. }
  252. BOOL SecurityIdsMatch(BYTE* pbSecurityId1, DWORD dwLen1, BYTE* pbSecurityId2, DWORD dwLen2)
  253. {
  254. //ASSERT((pbSecurityId1 && pbSecurityId2 && (dwLen1 > 0) && (dwLen2 > 0)));
  255. ComparisonState currState;
  256. BOOL bRetval = FALSE;
  257. //BOOL bRetval = ((dwLen1 == dwLen2) && (0 == memcmp(pbSecurityId1, pbSecurityId2, dwLen1)));
  258. BYTE *pCurr1, *pCurr2;
  259. DWORD dwDomainLen1, dwDomainLen2; //sizes of securityId w/o protocol.
  260. pCurr1 = pbSecurityId1;
  261. while(*pCurr1++ != ':');
  262. dwDomainLen1 = (DWORD)(pCurr1-pbSecurityId1);
  263. pCurr2 = pbSecurityId2;
  264. while(*pCurr2++ != ':');
  265. dwDomainLen2 = (DWORD)(pCurr2-pbSecurityId2);
  266. DEBUG_ENTER((DBG_APP,
  267. Bool,
  268. "SecurityIdsMatch",
  269. "%#x, %d, domainLen=%d %#x, %d, domainLen=%d",
  270. pbSecurityId1, dwLen1, dwDomainLen1, pbSecurityId2, dwLen2, dwDomainLen2
  271. ));
  272. BYTE *pBase1, *pBase2;
  273. BYTE bLeftByte, bRightByte;
  274. DWORD cbSubstring1 = 0;
  275. BYTE *pSubstring2Start = NULL;
  276. BYTE *pSubstring2End = NULL;
  277. //pCurr1 is the shorter one
  278. if (dwDomainLen1 < dwDomainLen2)
  279. {
  280. pCurr1 = pbSecurityId1+dwLen1-1-sizeof(DWORD);
  281. pBase1 = pbSecurityId1;
  282. pCurr2 = pbSecurityId2+dwLen2-1-sizeof(DWORD);
  283. pBase2 = pbSecurityId2;
  284. }
  285. else
  286. {
  287. pCurr2 = pbSecurityId1+dwLen1-1-sizeof(DWORD);
  288. pBase2 = pbSecurityId1;
  289. pCurr1 = pbSecurityId2+dwLen2-1-sizeof(DWORD);
  290. pBase1 = pbSecurityId2;
  291. }
  292. /* compare zone dword
  293. if (memcmp(pCurr1, pCurr2, sizeof(DWORD)))
  294. goto End;
  295. */
  296. /* compare domains */
  297. currState = seenZone;
  298. while ((pCurr1 > pBase1) && (pCurr2 > pBase2))
  299. {
  300. if ((bLeftByte=*pCurr1--) == (bRightByte=*pCurr2--))
  301. {
  302. /* valid assumption? no ':' in domain name */
  303. //ASSERT(((currState==seenZone) && (bLeftByte == ':')))
  304. if ((bLeftByte == '.') && (currState < seen3Dots))
  305. {
  306. currState = (ComparisonState)(currState+1);
  307. switch (currState)
  308. {
  309. case seen1Dot:
  310. pSubstring2End = pCurr1;
  311. break;
  312. case seen2Dots:
  313. pSubstring2Start = pCurr1+2;
  314. break;
  315. }
  316. }
  317. else if (bLeftByte == ':')
  318. {
  319. currState = domainSame;
  320. break;
  321. }
  322. else if (currState == seenZone)
  323. cbSubstring1++;
  324. }
  325. else
  326. break;
  327. }
  328. switch (currState)
  329. {
  330. case seenZone:
  331. /* NOTE: this rules out http:ieinternal and http:foo.ieinternal not to be INCLUDED */
  332. /* The alternative is to risk http:com and http:www.microsoft.com */
  333. goto End;
  334. case seen1Dot:
  335. /* INCLUDE http:microsoft.com and http:www.microsoft.com,
  336. ( http:a.micro.com and http:b.micro.com included by seen2Dots )
  337. EXCLUDE http:co.uk and http:www.microsoft.co.uk
  338. and all else
  339. eg. http:amicrosoft.com and http:www.microsoft.com
  340. &
  341. http:microsoft.com and http:amicrosoft.com
  342. */
  343. if ((bLeftByte != ':') || (bRightByte != '.') || ((cbSubstring1 == 2) && IsKnown2ndSubstring(pCurr1+2, pSubstring2End)))
  344. goto End;
  345. break;
  346. case seen2Dots:
  347. /* INCLUDE http:ood.microsoft.com and http:food.microsoft.com
  348. INCLUDE http:a.co.uk and http:b.a.co.uk
  349. EXCLUDE http:www.microsoft.co.uk and http:www.amicrosoft.co.uk
  350. */
  351. if ((cbSubstring1 == 2) && IsKnown2ndSubstring(pSubstring2Start, pSubstring2End) && ((bLeftByte != ':') || (bRightByte != '.')))
  352. goto End;
  353. break;
  354. case seen3Dots:
  355. /* INCLUDES all cases including
  356. http:food.microsoft.co.uk and http:drink.microsoft.co.uk */
  357. case domainSame:
  358. /* INCLUDES all equal domain cases of all substring sizes, including intranet sites */
  359. break;
  360. }
  361. /* no longer compare the protocols.
  362. if we get to this point, then the SecurityId's match.
  363. */
  364. bRetval = TRUE;
  365. End:
  366. DEBUG_LEAVE(bRetval);
  367. return bRetval;
  368. }
  369. BOOL SecurityIdContainsScheme(BYTE* pbSecurityId, DWORD dwLen)
  370. {
  371. BYTE* pCurr = pbSecurityId;
  372. BOOL fRet = TRUE;
  373. while ( (DWORD)(pCurr-pbSecurityId) < dwLen )
  374. {
  375. if (*pCurr++ == ':')
  376. {
  377. goto End;
  378. break;
  379. }
  380. }
  381. fRet = FALSE;
  382. End:
  383. return fRet;
  384. }
  385. //returns S_OK if they match,
  386. // S_FALSE if they don't ( i.e. THIRD PARTY )
  387. STDAPI CompareSecurityIds(BYTE* pbSecurityId1, DWORD dwLen1, BYTE* pbSecurityId2, DWORD dwLen2, DWORD dwReserved)
  388. {
  389. DEBUG_ENTER((DBG_APP,
  390. Hresult,
  391. "CompareSecurityIds",
  392. "%#x, %#x, %#x, %#x, %#x",
  393. pbSecurityId1, dwLen1, pbSecurityId2, dwLen2, dwReserved
  394. ));
  395. HRESULT hr = E_INVALIDARG;
  396. BOOL fRet;
  397. //parameter validation
  398. if ((dwLen1 <= 0) || (!pbSecurityId1) || (dwLen2 <= 0) || (!pbSecurityId2))
  399. goto End;
  400. if (!SecurityIdContainsScheme(pbSecurityId1, dwLen1) ||
  401. !SecurityIdContainsScheme(pbSecurityId2, dwLen2))
  402. goto End;
  403. fRet = SecurityIdsMatch(pbSecurityId1, dwLen1, pbSecurityId2, dwLen2);
  404. if (fRet == TRUE)
  405. hr = S_OK;
  406. else
  407. hr = S_FALSE;
  408. End:
  409. DEBUG_LEAVE(hr);
  410. return hr;
  411. }
  412. BOOL CINet::IsThirdPartyUrl(LPCWSTR pwszUrl)
  413. {
  414. DEBUG_ENTER((DBG_APP,
  415. Bool,
  416. "CINet::IsThirdPartyUrl",
  417. "this=%#x, %.80wq",
  418. this, pwszUrl
  419. ));
  420. BOOL bRetval = TRUE; // be safe or sorry?
  421. HRESULT hr = NOERROR;
  422. BYTE bSID[MAX_SIZE_SECURITY_ID];
  423. DWORD cbSID = MAX_SIZE_SECURITY_ID;
  424. if(!SUCCEEDED(hr = EnsureSecurityManager()))
  425. {
  426. goto End;
  427. }
  428. if (_pbRootSecurityId == NULL)
  429. {
  430. // ASSERT(FALSE);
  431. goto End;
  432. }
  433. else if (_pbRootSecurityId == INVALID_P_ROOT_SECURITY_ID)
  434. {
  435. bRetval = FALSE;
  436. goto End;
  437. }
  438. hr = g_pSecurityManager->GetSecurityId( pwszUrl, bSID, &cbSID, 0 );
  439. if (FAILED(hr))
  440. goto End;
  441. bRetval = !SecurityIdsMatch(bSID, cbSID, _pbRootSecurityId, _cbRootSecurityId);
  442. End:
  443. DEBUG_LEAVE(bRetval);
  444. return bRetval;
  445. }
  446. BOOL CINet::IsThirdPartyUrl(LPCSTR pszUrl)
  447. {
  448. DEBUG_ENTER((DBG_APP,
  449. Bool,
  450. "CINet::IsThirdPartyUrl",
  451. "this=%#x, %.80q",
  452. this, pszUrl
  453. ));
  454. WCHAR pwszUrl[MAX_URL_SIZE];
  455. BOOL bRetval = TRUE; // be safe or sorry?
  456. if(MultiByteToWideChar(CP_ACP, 0, pszUrl, -1, pwszUrl, MAX_URL_SIZE))
  457. bRetval = IsThirdPartyUrl(pwszUrl);
  458. DEBUG_LEAVE(bRetval);
  459. return bRetval;
  460. }
  461. //+---------------------------------------------------------------------------
  462. //
  463. // Function: CreateKnownProtocolInstance
  464. //
  465. // Synopsis:
  466. //
  467. // Arguments: [dwProtId] --
  468. // [rclsid] --
  469. // [pUnkOuter] --
  470. // [riid] --
  471. // [ppUnk] --
  472. //
  473. // Returns:
  474. //
  475. // History: 11-01-1996 JohannP (Johann Posch) Created
  476. //
  477. // Notes:
  478. //
  479. //----------------------------------------------------------------------------
  480. HRESULT CreateKnownProtocolInstance(DWORD dwProtId, REFCLSID rclsid, IUnknown *pUnkOuter, REFIID riid, IUnknown **ppUnk)
  481. {
  482. DEBUG_ENTER((DBG_APP,
  483. Hresult,
  484. "CreateKnownProtocolInstance",
  485. "%#x, %#x, %#x, %#x, %#x",
  486. dwProtId, &rclsid, pUnkOuter, &riid, ppUnk
  487. ));
  488. PerfDbgLog(tagCINet, NULL, "+CreateKnownProtocolInstance");
  489. HRESULT hr = NOERROR;
  490. CINet *pCINet = NULL;
  491. PProtAssert((ppUnk));
  492. if (!ppUnk || (pUnkOuter && (riid != IID_IUnknown)) )
  493. {
  494. // Note: aggregation only works if asked for IUnknown
  495. PProtAssert((FALSE && "Dude, look up aggregation rules - need to ask for IUnknown"));
  496. hr = E_INVALIDARG;
  497. }
  498. #if 0
  499. else if (riid == IID_IOInetProtocolInfo)
  500. {
  501. PProtAssert((dwProtId != DLD_PROTOCOL_NONE));
  502. COInetProtocolInfo *pProtInfo = new COInetProtocolInfo(dwProtId);
  503. if (pProtInfo)
  504. {
  505. hr = pProtInfo->QueryInterface(IID_IOInetProtocolInfo, (void **)ppUnk);
  506. }
  507. else
  508. {
  509. hr = E_OUTOFMEMORY;
  510. }
  511. }
  512. #endif // 0
  513. else if (dwProtId != DLD_PROTOCOL_NONE)
  514. {
  515. CINet *pCINet = NULL;
  516. switch (dwProtId)
  517. {
  518. case DLD_PROTOCOL_LOCAL :
  519. case DLD_PROTOCOL_FILE :
  520. pCINet = new CINetFile(CLSID_FileProtocol,pUnkOuter);
  521. break;
  522. case DLD_PROTOCOL_HTTP :
  523. pCINet = new CINetHttp(CLSID_HttpProtocol,pUnkOuter);
  524. break;
  525. case DLD_PROTOCOL_FTP :
  526. pCINet = new CINetFtp(CLSID_FtpProtocol,pUnkOuter);
  527. break;
  528. case DLD_PROTOCOL_GOPHER :
  529. pCINet = new CINetGopher(CLSID_GopherProtocol,pUnkOuter);
  530. break;
  531. case DLD_PROTOCOL_HTTPS :
  532. pCINet = new CINetHttpS(CLSID_HttpSProtocol,pUnkOuter);
  533. break;
  534. case DLD_PROTOCOL_STREAM :
  535. pCINet = new CINetStream(CLSID_MkProtocol,pUnkOuter);
  536. break;
  537. default:
  538. PProtAssert((FALSE));
  539. hr = E_FAIL;
  540. }
  541. if (hr == NOERROR)
  542. {
  543. if (pCINet)
  544. {
  545. if (riid == IID_IUnknown)
  546. {
  547. // pCINet has refcount of 1 now
  548. // get the pUnkInner
  549. // pUnkInner does not addref pUnkOuter
  550. if (pUnkOuter && ppUnk)
  551. {
  552. *ppUnk = pCINet->GetIUnkInner(TRUE);
  553. // addref the outer object since releasing pCINet will go cause a release on pUnkOuter
  554. TransAssert((*ppUnk));
  555. }
  556. }
  557. else
  558. {
  559. if (riid == IID_IOInetProtocol)
  560. {
  561. // ok, got the right interface already
  562. *ppUnk = (IOInetProtocol *)pCINet;
  563. }
  564. else
  565. {
  566. hr = pCINet->QueryInterface(riid, (void **)ppUnk);
  567. // remove extra refcount
  568. pCINet->Release();
  569. }
  570. }
  571. }
  572. else
  573. {
  574. hr = E_OUTOFMEMORY;
  575. }
  576. }
  577. }
  578. else
  579. {
  580. //load the protocol by looking up the registry
  581. hr = E_FAIL;
  582. }
  583. PerfDbgLog1(tagCINet, NULL, "-CreateKnownProtocolInstance(hr:%lx)", hr);
  584. DEBUG_LEAVE(hr);
  585. return hr;
  586. }
  587. ProtocolInfo rgKnownProts[] =
  588. {
  589. { L"http" , "http" , DLD_PROTOCOL_HTTP , (CLSID *) &CLSID_HttpProtocol , sizeof("http") - 1 }
  590. ,{ L"file" , "file" , DLD_PROTOCOL_FILE , (CLSID *) &CLSID_FileProtocol , sizeof("file") - 1 }
  591. ,{ L"ftp" , "ftp" , DLD_PROTOCOL_FTP , (CLSID *) &CLSID_FtpProtocol , sizeof("ftp") - 1 }
  592. ,{ L"https" , "https" , DLD_PROTOCOL_HTTPS , (CLSID *) &CLSID_HttpSProtocol , sizeof("http") - 1 }
  593. ,{ L"mk" , "mk" , DLD_PROTOCOL_STREAM , (CLSID *) &CLSID_MkProtocol , sizeof("mk") - 1 }
  594. ,{ L"gopher", "Gopher" , DLD_PROTOCOL_GOPHER , (CLSID *) &CLSID_GopherProtocol, sizeof("gopher") - 1 }
  595. ,{ L"local" , "local" , DLD_PROTOCOL_LOCAL , (CLSID *) &CLSID_FileProtocol , sizeof("local") - 1 }
  596. };
  597. typedef struct tagInterErrorToHResult
  598. {
  599. DWORD dwError;
  600. HRESULT hresult;
  601. } InterErrorToHResult;
  602. InterErrorToHResult INetError[] =
  603. {
  604. 0 ,NOERROR
  605. ,ERROR_INTERNET_OUT_OF_HANDLES ,INET_E_DOWNLOAD_FAILURE
  606. ,ERROR_INTERNET_TIMEOUT ,INET_E_CONNECTION_TIMEOUT
  607. ,ERROR_INTERNET_EXTENDED_ERROR ,INET_E_DOWNLOAD_FAILURE
  608. ,ERROR_INTERNET_INTERNAL_ERROR ,INET_E_DOWNLOAD_FAILURE
  609. ,ERROR_INTERNET_INVALID_URL ,INET_E_INVALID_URL
  610. ,ERROR_INTERNET_UNRECOGNIZED_SCHEME ,INET_E_UNKNOWN_PROTOCOL
  611. ,ERROR_INTERNET_NAME_NOT_RESOLVED ,INET_E_RESOURCE_NOT_FOUND
  612. ,ERROR_INTERNET_PROTOCOL_NOT_FOUND ,INET_E_UNKNOWN_PROTOCOL
  613. ,ERROR_INTERNET_INVALID_OPTION ,INET_E_DOWNLOAD_FAILURE
  614. ,ERROR_INTERNET_BAD_OPTION_LENGTH ,INET_E_DOWNLOAD_FAILURE
  615. ,ERROR_INTERNET_OPTION_NOT_SETTABLE ,INET_E_DOWNLOAD_FAILURE
  616. ,ERROR_INTERNET_SHUTDOWN ,INET_E_DOWNLOAD_FAILURE
  617. ,ERROR_INTERNET_INCORRECT_USER_NAME ,INET_E_DOWNLOAD_FAILURE
  618. ,ERROR_INTERNET_INCORRECT_PASSWORD ,INET_E_DOWNLOAD_FAILURE
  619. ,ERROR_INTERNET_LOGIN_FAILURE ,INET_E_DOWNLOAD_FAILURE
  620. ,ERROR_INTERNET_INVALID_OPERATION ,INET_E_DOWNLOAD_FAILURE
  621. ,ERROR_INTERNET_OPERATION_CANCELLED ,INET_E_DOWNLOAD_FAILURE
  622. ,ERROR_INTERNET_INCORRECT_HANDLE_TYPE ,INET_E_DOWNLOAD_FAILURE
  623. ,ERROR_INTERNET_INCORRECT_HANDLE_STATE ,INET_E_DOWNLOAD_FAILURE
  624. ,ERROR_INTERNET_NOT_PROXY_REQUEST ,INET_E_DOWNLOAD_FAILURE
  625. ,ERROR_INTERNET_REGISTRY_VALUE_NOT_FOUND ,INET_E_DOWNLOAD_FAILURE
  626. ,ERROR_INTERNET_BAD_REGISTRY_PARAMETER ,INET_E_DOWNLOAD_FAILURE
  627. ,ERROR_INTERNET_NO_DIRECT_ACCESS ,INET_E_DOWNLOAD_FAILURE
  628. ,ERROR_INTERNET_NO_CONTEXT ,INET_E_DOWNLOAD_FAILURE
  629. ,ERROR_INTERNET_NO_CALLBACK ,INET_E_DOWNLOAD_FAILURE
  630. ,ERROR_INTERNET_REQUEST_PENDING ,INET_E_DOWNLOAD_FAILURE
  631. ,ERROR_INTERNET_INCORRECT_FORMAT ,INET_E_DOWNLOAD_FAILURE
  632. ,ERROR_INTERNET_ITEM_NOT_FOUND ,INET_E_OBJECT_NOT_FOUND
  633. ,ERROR_INTERNET_CANNOT_CONNECT ,INET_E_RESOURCE_NOT_FOUND
  634. ,ERROR_INTERNET_CONNECTION_ABORTED ,INET_E_DOWNLOAD_FAILURE
  635. ,ERROR_INTERNET_CONNECTION_RESET ,INET_E_DOWNLOAD_FAILURE
  636. ,ERROR_INTERNET_FORCE_RETRY ,INET_E_DOWNLOAD_FAILURE
  637. ,ERROR_INTERNET_INVALID_PROXY_REQUEST ,INET_E_DOWNLOAD_FAILURE
  638. ,ERROR_INTERNET_NEED_UI ,INET_E_DOWNLOAD_FAILURE
  639. ,0 ,INET_E_DOWNLOAD_FAILURE
  640. ,ERROR_INTERNET_HANDLE_EXISTS ,INET_E_DOWNLOAD_FAILURE
  641. ,ERROR_INTERNET_SEC_CERT_DATE_INVALID ,INET_E_SECURITY_PROBLEM
  642. ,ERROR_INTERNET_SEC_CERT_CN_INVALID ,INET_E_SECURITY_PROBLEM
  643. ,ERROR_INTERNET_HTTP_TO_HTTPS_ON_REDIR ,INET_E_DOWNLOAD_FAILURE
  644. ,ERROR_INTERNET_HTTPS_TO_HTTP_ON_REDIR ,INET_E_DOWNLOAD_FAILURE
  645. ,ERROR_INTERNET_MIXED_SECURITY ,INET_E_SECURITY_PROBLEM
  646. ,ERROR_INTERNET_CHG_POST_IS_NON_SECURE ,INET_E_SECURITY_PROBLEM
  647. ,ERROR_INTERNET_POST_IS_NON_SECURE ,INET_E_SECURITY_PROBLEM
  648. ,ERROR_INTERNET_CLIENT_AUTH_CERT_NEEDED ,INET_E_SECURITY_PROBLEM
  649. ,ERROR_INTERNET_INVALID_CA ,INET_E_SECURITY_PROBLEM
  650. ,ERROR_INTERNET_CLIENT_AUTH_NOT_SETUP ,INET_E_SECURITY_PROBLEM
  651. ,ERROR_INTERNET_SEC_CERT_REV_FAILED ,INET_E_SECURITY_PROBLEM
  652. ,ERROR_INTERNET_SEC_CERT_REVOKED ,INET_E_SECURITY_PROBLEM
  653. ,ERROR_INTERNET_FORTEZZA_LOGIN_NEEDED ,INET_E_SECURITY_PROBLEM
  654. ,ERROR_INTERNET_ASYNC_THREAD_FAILED ,INET_E_DOWNLOAD_FAILURE
  655. ,ERROR_INTERNET_REDIRECT_SCHEME_CHANGE ,INET_E_DOWNLOAD_FAILURE
  656. };
  657. // list of non-sequential errors
  658. InterErrorToHResult INetErrorExtended[] =
  659. {
  660. ERROR_FTP_TRANSFER_IN_PROGRESS ,INET_E_DOWNLOAD_FAILURE
  661. ,ERROR_FTP_DROPPED ,INET_E_DOWNLOAD_FAILURE
  662. ,ERROR_GOPHER_PROTOCOL_ERROR ,INET_E_DOWNLOAD_FAILURE
  663. ,ERROR_GOPHER_NOT_FILE ,INET_E_DOWNLOAD_FAILURE
  664. ,ERROR_GOPHER_DATA_ERROR ,INET_E_DOWNLOAD_FAILURE
  665. ,ERROR_GOPHER_END_OF_DATA ,INET_E_DOWNLOAD_FAILURE
  666. ,ERROR_GOPHER_INVALID_LOCATOR ,INET_E_DOWNLOAD_FAILURE
  667. ,ERROR_GOPHER_INCORRECT_LOCATOR_TYPE ,INET_E_DOWNLOAD_FAILURE
  668. ,ERROR_GOPHER_NOT_GOPHER_PLUS ,INET_E_DOWNLOAD_FAILURE
  669. ,ERROR_GOPHER_ATTRIBUTE_NOT_FOUND ,INET_E_DOWNLOAD_FAILURE
  670. ,ERROR_GOPHER_UNKNOWN_LOCATOR ,INET_E_DOWNLOAD_FAILURE
  671. ,ERROR_HTTP_HEADER_NOT_FOUND ,INET_E_DOWNLOAD_FAILURE
  672. ,ERROR_HTTP_DOWNLEVEL_SERVER ,INET_E_DOWNLOAD_FAILURE
  673. ,ERROR_HTTP_INVALID_SERVER_RESPONSE ,INET_E_DOWNLOAD_FAILURE
  674. ,ERROR_HTTP_INVALID_HEADER ,INET_E_DOWNLOAD_FAILURE
  675. ,ERROR_HTTP_INVALID_QUERY_REQUEST ,INET_E_DOWNLOAD_FAILURE
  676. ,ERROR_HTTP_HEADER_ALREADY_EXISTS ,INET_E_DOWNLOAD_FAILURE
  677. ,ERROR_HTTP_REDIRECT_FAILED ,INET_E_REDIRECT_FAILED
  678. ,ERROR_HTTP_REDIRECT_NEEDS_CONFIRMATION ,INET_E_DOWNLOAD_FAILURE
  679. ,ERROR_INTERNET_SECURITY_CHANNEL_ERROR ,INET_E_DOWNLOAD_FAILURE
  680. ,ERROR_INTERNET_UNABLE_TO_CACHE_FILE ,INET_E_DOWNLOAD_FAILURE
  681. ,ERROR_INTERNET_TCPIP_NOT_INSTALLED ,INET_E_DOWNLOAD_FAILURE
  682. ,ERROR_HTTP_NOT_REDIRECTED ,INET_E_DOWNLOAD_FAILURE
  683. ,ERROR_INTERNET_HTTPS_HTTP_SUBMIT_REDIR ,INET_E_DOWNLOAD_FAILURE
  684. };
  685. //+---------------------------------------------------------------------------
  686. //
  687. // Function: IsKnownOInetProtocolClass
  688. //
  689. // Synopsis:
  690. //
  691. // Arguments: [pclsid] --
  692. //
  693. // Returns:
  694. //
  695. // History: 11-01-1996 JohannP (Johann Posch) Created
  696. //
  697. // Notes:
  698. //
  699. //----------------------------------------------------------------------------
  700. DWORD IsKnownOInetProtocolClass(CLSID *pclsid)
  701. {
  702. DEBUG_ENTER((DBG_APP,
  703. Dword,
  704. "IsKnownOInetProtocolClass",
  705. "%#x",
  706. pclsid
  707. ));
  708. PProtAssert((pclsid));
  709. DWORD dwRet = DLD_PROTOCOL_NONE;
  710. int i = 0;
  711. int cSize = sizeof(rgKnownProts)/sizeof(ProtocolInfo);
  712. if (pclsid)
  713. {
  714. for (i = 0; i < cSize; ++i)
  715. {
  716. if (*pclsid == *rgKnownProts[i].pClsID)
  717. {
  718. dwRet = rgKnownProts[i].dwId;
  719. i = cSize;
  720. }
  721. }
  722. }
  723. DEBUG_LEAVE(dwRet);
  724. return dwRet;
  725. }
  726. //+---------------------------------------------------------------------------
  727. //
  728. // Function: IsKnownProtocol
  729. //
  730. // Synopsis: looks up if an protocol handler exist for a given url
  731. //
  732. // Arguments: [wzProtocol] --
  733. //
  734. // Returns:
  735. //
  736. // History: 11-01-1996 JohannP (Johann Posch) Created
  737. //
  738. // Notes: used at many place inside urlmon
  739. //
  740. //----------------------------------------------------------------------------
  741. DWORD IsKnownProtocol(LPCWSTR wzProtocol)
  742. {
  743. DEBUG_ENTER((DBG_APP,
  744. Dword,
  745. "IsKnownProtocol",
  746. "%#.80wq",
  747. wzProtocol
  748. ));
  749. DWORD dwRet = DLD_PROTOCOL_NONE;
  750. int i = 0;
  751. int cSize = sizeof(rgKnownProts)/sizeof(ProtocolInfo);
  752. for (i = 0; i < cSize; ++i)
  753. {
  754. if (!StrCmpNICW(wzProtocol, rgKnownProts[i].pwzProtocol, rgKnownProts[i].protlen))
  755. {
  756. dwRet = rgKnownProts[i].dwId;
  757. if ((DLD_PROTOCOL_HTTP == dwRet) &&
  758. ((wzProtocol[4] == L's') ||
  759. (wzProtocol[4] == L'S')))
  760. {
  761. dwRet = DLD_PROTOCOL_HTTPS;
  762. }
  763. break;
  764. }
  765. }
  766. DEBUG_LEAVE(dwRet);
  767. return dwRet;
  768. }
  769. //+---------------------------------------------------------------------------
  770. //
  771. // Function: GetKnownOInetProtocolClsID
  772. //
  773. // Synopsis:
  774. //
  775. // Arguments: [dwProtoId] --
  776. //
  777. // Returns:
  778. //
  779. // History: 11-01-1996 JohannP (Johann Posch) Created
  780. //
  781. // Notes:
  782. //
  783. //----------------------------------------------------------------------------
  784. CLSID *GetKnownOInetProtocolClsID(DWORD dwProtoId)
  785. {
  786. DEBUG_ENTER((DBG_APP,
  787. Pointer,
  788. "GetKnownOInetProtocolClsID",
  789. "%#x",
  790. dwProtoId
  791. ));
  792. PerfDbgLog1(tagCINet, NULL, "GetKnownOInetProtocolClsID (dwProtoId:%lx)", dwProtoId);
  793. CLSID *pclsid = 0;
  794. int cSize = sizeof(rgKnownProts)/sizeof(ProtocolInfo);
  795. for (int i = 0; i < cSize; ++i)
  796. {
  797. if (dwProtoId == rgKnownProts[i].dwId )
  798. {
  799. pclsid = rgKnownProts[i].pClsID;
  800. i = cSize;
  801. }
  802. }
  803. DEBUG_LEAVE(pclsid);
  804. return pclsid;
  805. }
  806. //+---------------------------------------------------------------------------
  807. //
  808. // Method: CINet::QueryInterface
  809. //
  810. // Synopsis:
  811. //
  812. // Arguments: [riid] --
  813. // [ppvObj] --
  814. //
  815. // Returns:
  816. //
  817. // History: 10-29-1996 JohannP (Johann Posch) Created
  818. //
  819. // Notes:
  820. //
  821. //----------------------------------------------------------------------------
  822. STDMETHODIMP CINet::QueryInterface(REFIID riid, void **ppvObj)
  823. {
  824. DEBUG_ENTER((DBG_APP,
  825. Hresult,
  826. "CINet::IUnknown::QueryInterface",
  827. "this=%#x, %#x, %#x",
  828. this, &riid, ppvObj
  829. ));
  830. VDATEPTROUT(ppvObj, void *);
  831. VDATETHIS(this);
  832. HRESULT hr = NOERROR;
  833. PerfDbgLog(tagCINet, this, "+CINet::QueryInterface");
  834. if (riid == IID_IOInetPriority)
  835. {
  836. *ppvObj = (IOInetPriority *) this;
  837. AddRef();
  838. }
  839. else
  840. {
  841. hr = _pUnkOuter->QueryInterface(riid, ppvObj);
  842. }
  843. PerfDbgLog1(tagCINet, this, "-CINet::QueryInterface (hr:%lx)", hr);
  844. DEBUG_LEAVE(hr);
  845. return hr;
  846. }
  847. //+---------------------------------------------------------------------------
  848. //
  849. // Function: CINet::AddRef
  850. //
  851. // Synopsis:
  852. //
  853. // Arguments: [ULONG] --
  854. //
  855. // Returns:
  856. //
  857. // History: 10-29-1996 JohannP (Johann Posch) Created
  858. //
  859. // Notes:
  860. //
  861. //----------------------------------------------------------------------------
  862. STDMETHODIMP_(ULONG) CINet::AddRef(void)
  863. {
  864. DEBUG_ENTER((DBG_APP,
  865. Dword,
  866. "CINet::IUnknown::AddRef",
  867. "this=%#x",
  868. this
  869. ));
  870. PerfDbgLog(tagCINet, this, "+CINet::AddRef");
  871. LONG lRet = _pUnkOuter->AddRef();
  872. PerfDbgLog1(tagCINet, this, "-CINet::AddRef (cRefs:%ld)", lRet);
  873. DEBUG_LEAVE(lRet);
  874. return lRet;
  875. }
  876. //+---------------------------------------------------------------------------
  877. //
  878. // Function: CINet::Release
  879. //
  880. // Synopsis:
  881. //
  882. // Arguments: [ULONG] --
  883. //
  884. // Returns:
  885. //
  886. // History: 10-29-1996 JohannP (Johann Posch) Created
  887. //
  888. // Notes:
  889. //
  890. //----------------------------------------------------------------------------
  891. STDMETHODIMP_(ULONG) CINet::Release(void)
  892. {
  893. DEBUG_ENTER((DBG_APP,
  894. Dword,
  895. "CINet::IUnknown::Release",
  896. "this=%#x",
  897. this
  898. ));
  899. PerfDbgLog(tagCINet, this, "+CINet::Release");
  900. LONG lRet = _pUnkOuter->Release();
  901. PerfDbgLog1(tagCINet, this, "-CINet::Release (cRefs:%ld)", lRet);
  902. DEBUG_LEAVE(lRet);
  903. return lRet;
  904. }
  905. //+---------------------------------------------------------------------------
  906. //
  907. // Method: CINet::Start
  908. //
  909. // Synopsis:
  910. //
  911. // Arguments: [pwzUrl] --
  912. // [pTrans] --
  913. // [pOIBindInfo] --
  914. // [grfSTI] --
  915. // [dwReserved] --
  916. //
  917. // Returns:
  918. //
  919. // History: 10-29-1996 JohannP (Johann Posch) Created
  920. //
  921. // Notes:
  922. //
  923. //----------------------------------------------------------------------------
  924. STDMETHODIMP CINet::Start(LPCWSTR pwzUrl, IOInetProtocolSink *pTrans, IOInetBindInfo *pOIBindInfo,
  925. DWORD grfSTI, DWORD_PTR dwReserved)
  926. {
  927. DEBUG_ENTER((DBG_APP,
  928. Hresult,
  929. "CINet::IInternetProtocolRoot::Start",
  930. "this=%#x, %.200wq, %#x, %#x, %#x, %#x",
  931. this, pwzUrl, pTrans, pOIBindInfo, grfSTI, dwReserved
  932. ));
  933. PerfDbgLog(tagCINet, this, "+CINet::Start");
  934. HRESULT hr = NOERROR;
  935. //char szURL[MAX_URL_SIZE];
  936. DWORD dwUrlSize = 0;
  937. DWORD dwMaxUTF8Len = 0;
  938. BOOL fUTF8Enabled = FALSE;
  939. BOOL fUTF8Required = FALSE;
  940. PProtAssert((!_pCTrans && pOIBindInfo && pTrans));
  941. PProtAssert((_pwzUrl == NULL));
  942. if ( !(grfSTI & PI_PARSE_URL))
  943. {
  944. _pCTrans = pTrans;
  945. _pCTrans->AddRef();
  946. _pOIBindInfo = pOIBindInfo;
  947. _pOIBindInfo->AddRef();
  948. _pwzUrl = OLESTRDuplicate((LPWSTR)pwzUrl);
  949. }
  950. _BndInfo.cbSize = sizeof(BINDINFO);
  951. hr = pOIBindInfo->GetBindInfo(&_grfBindF, &_BndInfo);
  952. DEBUG_ENTER((DBG_APP,
  953. Hresult,
  954. "EXTERNAL_CLIENT::GetBindInfo",
  955. "this=%#x, flags=%#x, pBindInfo=%#x",
  956. this, _grfBindF, pOIBindInfo
  957. ));
  958. DEBUG_LEAVE(hr);
  959. if( hr != NOERROR )
  960. {
  961. goto End;
  962. }
  963. /************************************************************************
  964. // szURL does not seem to be used, am I missing something?
  965. // szURL is 2K buffer on stack! Let's remove this code at all.
  966. // DanpoZ (98/02/20)
  967. // Do we need to append the extra data to the url?
  968. if (_BndInfo.szExtraInfo)
  969. {
  970. // append extra info at the end of the url
  971. // Make sure we don't overflow the URL
  972. if (CchWzLen(_BndInfo.szExtraInfo) + CchWzLen(pwzUrl) >= MAX_URL_SIZE)
  973. {
  974. hr = E_INVALIDARG;
  975. goto End;
  976. }
  977. W2A(pwzUrl, szURL, MAX_URL_SIZE, _BndInfo.dwCodePage);
  978. // Append the extra data to the url. Note that we have already
  979. // checked for overflow, so we need not worry about it here.
  980. W2A(_BndInfo.szExtraInfo, szURL + CchSzLen(szURL), MAX_URL_SIZE, _BndInfo.dwCodePage);
  981. }
  982. else
  983. {
  984. // Make sure we don't overflow the URL
  985. if (CchWzLen(pwzUrl) + 1 > MAX_URL_SIZE)
  986. {
  987. hr = E_INVALIDARG;
  988. goto End;
  989. }
  990. W2A(pwzUrl, szURL, MAX_URL_SIZE, _BndInfo.dwCodePage);
  991. }
  992. ************************************************************************/
  993. // no need to check the length of pwzUrl, this has been done already
  994. if( !_BndInfo.dwCodePage )
  995. _BndInfo.dwCodePage = GetACP();
  996. // utf8 enabled?
  997. fUTF8Enabled = UTF8Enabled();
  998. if( fUTF8Enabled )
  999. {
  1000. dwUrlSize = CountUnicodeToUtf8(pwzUrl, wcslen(pwzUrl), TRUE);
  1001. DWORD dwMB = StrLenMultiByteWithMlang(pwzUrl, _BndInfo.dwCodePage);
  1002. if( dwMB > dwUrlSize )
  1003. {
  1004. dwUrlSize = dwMB;
  1005. }
  1006. }
  1007. else
  1008. {
  1009. dwUrlSize = StrLenMultiByteWithMlang(pwzUrl, _BndInfo.dwCodePage);
  1010. }
  1011. if( !dwUrlSize )
  1012. {
  1013. hr = E_INVALIDARG;
  1014. goto End;
  1015. }
  1016. if( CUrlInitBasic(dwUrlSize) )
  1017. {
  1018. //W2A(pwzUrl, _pszBaseURL, dwUrlSize, _BndInfo.dwCodePage);
  1019. ConvertUnicodeUrl(
  1020. pwzUrl, // (IN) unicode URL
  1021. _pszBaseURL, // (OUT) multibyte URL
  1022. dwUrlSize, // (IN) multibyte URL length
  1023. _BndInfo.dwCodePage, // (IN) codepage
  1024. fUTF8Enabled, // (IN) UTF-8 conversion enabled?
  1025. &fUTF8Required
  1026. );
  1027. }
  1028. else
  1029. {
  1030. hr = E_OUTOFMEMORY;
  1031. goto End;
  1032. }
  1033. {
  1034. // Init the Embedded Filter
  1035. if( _pEmbdFilter )
  1036. {
  1037. delete _pEmbdFilter;
  1038. _pEmbdFilter = NULL;
  1039. }
  1040. _pEmbdFilter = new CINetEmbdFilter( this, _pCTrans );
  1041. if( !_pEmbdFilter )
  1042. {
  1043. hr = E_OUTOFMEMORY;
  1044. goto End;
  1045. }
  1046. if(!_pEmbdFilter->IsInited())
  1047. {
  1048. delete _pEmbdFilter;
  1049. _pEmbdFilter = NULL;
  1050. hr = E_OUTOFMEMORY;
  1051. goto End;
  1052. }
  1053. // For sanity checks later via IsEmbdFilterOk():
  1054. _dwEmbdFilter = *(DWORD *)_pEmbdFilter;
  1055. }
  1056. if (!ParseUrl(fUTF8Required, pwzUrl, _BndInfo.dwCodePage))
  1057. {
  1058. _hrError = INET_E_INVALID_URL;
  1059. hr = MK_E_SYNTAX;
  1060. }
  1061. else if ( !(grfSTI & PI_PARSE_URL))
  1062. {
  1063. g_cInetState.HandleState();
  1064. PProtAssert((_pCTrans));
  1065. if( !(_grfBindF & BINDF_FROMURLMON) && IsEmbdFilterOk() )
  1066. {
  1067. _pEmbdFilter->ReportProgress(BINDSTATUS_DIRECTBIND, 0);
  1068. }
  1069. hr = INetAsyncStart();
  1070. }
  1071. End:
  1072. PerfDbgLog1(tagCINet, this, "-CINet::Start (hr:%lx)", hr);
  1073. if( hr == E_PENDING )
  1074. {
  1075. // hack, CTransact will warp E_PENDING with NOERROR and return
  1076. // it to client, if we do not have CTrans wrapper (not aggregrated)
  1077. // we should return NOERROR.
  1078. if( _pUnkOuter == &_Unknown )
  1079. {
  1080. hr = NOERROR;
  1081. }
  1082. }
  1083. DEBUG_LEAVE(hr);
  1084. return hr;
  1085. }
  1086. //+---------------------------------------------------------------------------
  1087. //
  1088. // Method: CINet::Continue
  1089. //
  1090. // Synopsis:
  1091. //
  1092. // Arguments: [pStateInfoIn] --
  1093. //
  1094. // Returns:
  1095. //
  1096. // History: 10-29-1996 JohannP (Johann Posch) Created
  1097. //
  1098. // Notes:
  1099. //
  1100. //----------------------------------------------------------------------------
  1101. STDMETHODIMP CINet::Continue(PROTOCOLDATA *pStateInfoIn)
  1102. {
  1103. DEBUG_ENTER((DBG_APP,
  1104. Hresult,
  1105. "CINet::IInternetProtocolRoot::Continue",
  1106. "this=%#x, %#x",
  1107. this, pStateInfoIn
  1108. ));
  1109. HRESULT hr = E_FAIL;
  1110. if(IsEmbdFilterOk())
  1111. hr = _pEmbdFilter->Continue(pStateInfoIn);
  1112. DEBUG_LEAVE(hr);
  1113. return hr;
  1114. }
  1115. STDMETHODIMP CINet::MyContinue(PROTOCOLDATA *pStateInfoIn)
  1116. {
  1117. DEBUG_ENTER((DBG_APP,
  1118. Hresult,
  1119. "CINet::MyContinue",
  1120. "this=%#x, %#x",
  1121. this, pStateInfoIn
  1122. ));
  1123. PerfDbgLog(tagCINet, this, "+CINet::Continue");
  1124. HRESULT hr = NOERROR;
  1125. PProtAssert((pStateInfoIn->pData && !pStateInfoIn->cbData));
  1126. // check if the inete state changed
  1127. g_cInetState.HandleState();
  1128. OnINetInternal((DWORD_PTR) pStateInfoIn->pData);
  1129. if( !(_grfBindF & BINDF_FROMURLMON) )
  1130. {
  1131. //
  1132. // if the BindInfo is created from heap by CINet
  1133. // we need to delete it from here
  1134. //
  1135. delete pStateInfoIn;
  1136. }
  1137. PerfDbgLog1(tagCINet, this, "-CINet::Continue (hr:%lx)", hr);
  1138. DEBUG_LEAVE(hr);
  1139. return hr;
  1140. }
  1141. //+---------------------------------------------------------------------------
  1142. //
  1143. // Method: CINet::Abort
  1144. //
  1145. // Synopsis:
  1146. //
  1147. // Arguments: [hrReason] --
  1148. // [dwOptions] --
  1149. //
  1150. // Returns:
  1151. //
  1152. // History: 10-29-1996 JohannP (Johann Posch) Created
  1153. //
  1154. // Notes:
  1155. //
  1156. //----------------------------------------------------------------------------
  1157. STDMETHODIMP CINet::Abort(HRESULT hrReason, DWORD dwOptions)
  1158. {
  1159. DEBUG_ENTER((DBG_APP,
  1160. Hresult,
  1161. "CINet::IInternetProtocolRoot::Abort",
  1162. "this=%#x, %#x, %#x",
  1163. this, hrReason, dwOptions
  1164. ));
  1165. HRESULT hr = NOERROR;
  1166. if( _pEmbdFilter )
  1167. {
  1168. hr = _pEmbdFilter->Abort(hrReason, dwOptions);
  1169. }
  1170. DEBUG_LEAVE(hr);
  1171. return hr;
  1172. }
  1173. STDMETHODIMP CINet::MyAbort(HRESULT hrReason, DWORD dwOptions)
  1174. {
  1175. DEBUG_ENTER((DBG_APP,
  1176. Hresult,
  1177. "CINet::MyAbort",
  1178. "this=%#x, %#x, %#x",
  1179. this, hrReason, dwOptions
  1180. ));
  1181. PerfDbgLog(tagCINet, this, "+CINet::Abort");
  1182. HRESULT hr = NOERROR;
  1183. PProtAssert((_pCTrans));
  1184. hr = ReportResultAndStop(hrReason);
  1185. PerfDbgLog1(tagCINet, this, "-CINet::Abort (hr:%lx)", hr);
  1186. DEBUG_LEAVE(hr);
  1187. return hr;
  1188. }
  1189. //+---------------------------------------------------------------------------
  1190. //
  1191. // Method: CINet::Terminate
  1192. //
  1193. // Synopsis:
  1194. //
  1195. // Arguments: [dwOptions] --
  1196. //
  1197. // Returns:
  1198. //
  1199. // History: 10-29-1996 JohannP (Johann Posch) Created
  1200. //
  1201. // Notes:
  1202. //
  1203. //----------------------------------------------------------------------------
  1204. STDMETHODIMP CINet::Terminate(DWORD dwOptions)
  1205. {
  1206. DEBUG_ENTER((DBG_APP,
  1207. Hresult,
  1208. "CINet::IInternetProtocolRoot::Terminate",
  1209. "this=%#x, %#x",
  1210. this, dwOptions
  1211. ));
  1212. // in case we failed on :Start, _pEmbdFilter is
  1213. // not in place, however, Terminate might be
  1214. // called so we have to call MyTerminate directly
  1215. HRESULT hr = NOERROR;
  1216. if( _pEmbdFilter )
  1217. {
  1218. hr = _pEmbdFilter->Terminate(dwOptions);
  1219. }
  1220. else
  1221. {
  1222. hr = MyTerminate(dwOptions);
  1223. }
  1224. DEBUG_LEAVE(hr);
  1225. return hr;
  1226. }
  1227. /*
  1228. * This function will only be called into after MyTerminate has been called -
  1229. * since only InternetCloseHandle called in MyTerminate should trigger a handle-closing callback.
  1230. *
  1231. * No synchronization may be required because :
  1232. *
  1233. * 1. all operations at this point using the handle should have
  1234. been done with since the handle has been destroyed ( hence no Reads in progress. )
  1235. 2. if we find that we need to synchronize access to this, we must correspondinly synchronize
  1236. all access to the _pCTrans object from CINet. Hopefully, this is not required because
  1237. we should get handleclosing callback from wininet only after we have exited all callbacks.
  1238. 3. the only other place _pCTrans can be touched from is Reads from above which shouldn't be
  1239. happening if this is closed as a result of being aborted or terminated cleanly.
  1240. *
  1241. The objective of this new function is to let the _pCTrans connection live until wininet is done
  1242. with context use - else witness ugly race condition in bug 2270.
  1243. ReleaseBindInfo() happening here to get around bug 19809, which again is triggered by IBinding::Abort
  1244. situations in stress.
  1245. */
  1246. VOID CINet::ReleaseTransAndBindInfo()
  1247. {
  1248. DEBUG_ENTER((DBG_APP,
  1249. None,
  1250. "CINet::ReleaseTransAndBindInfo",
  1251. "this=%#x, %#x",
  1252. this, _pCTrans
  1253. ));
  1254. if (!_fHandlesRecycled)
  1255. {
  1256. PProtAssert((_pCTrans));
  1257. PProtAssert((_dwState == INetState_DONE) || (_dwState == INetState_ERROR));
  1258. PProtAssert((_dwIsA == DLD_PROTOCOL_HTTP) || (_dwIsA == DLD_PROTOCOL_HTTPS) || (_dwIsA == DLD_PROTOCOL_FILE) || (_dwIsA == DLD_PROTOCOL_GOPHER));
  1259. // Hopefully, this stays an assert.
  1260. // scenario where abort is called before/during the OpenRequest/OpenUrl call.
  1261. PProtAssert((_HandleStateRequest == HandleState_Closed));
  1262. if (_pCTrans)
  1263. {
  1264. _pCTrans->Release();
  1265. _pCTrans = NULL;
  1266. }
  1267. ReleaseBindInfo(&_BndInfo);
  1268. }
  1269. DEBUG_LEAVE(0);
  1270. }
  1271. STDMETHODIMP CINet::MyTerminate(DWORD dwOptions)
  1272. {
  1273. DEBUG_ENTER((DBG_APP,
  1274. Hresult,
  1275. "CINet::MyTerminate",
  1276. "this=%#x, %#x",
  1277. this, dwOptions
  1278. ));
  1279. PerfDbgLog(tagCINet, this, "+CINet::Terminate");
  1280. HRESULT hr = NOERROR;
  1281. BOOL fReleaseBindInfo = FALSE;
  1282. //should be called once
  1283. PProtAssert((_pCTrans));
  1284. if (_pOIBindInfo)
  1285. {
  1286. _pOIBindInfo->Release();
  1287. _pOIBindInfo = NULL;
  1288. }
  1289. if (_pServiceProvider)
  1290. {
  1291. _pServiceProvider->Release();
  1292. _pServiceProvider = NULL;
  1293. }
  1294. if (_pCTrans)
  1295. {
  1296. // release all the handles if unless
  1297. // the request was locked
  1298. if (!_fLocked && !_hLockHandle)
  1299. {
  1300. TerminateRequest();
  1301. }
  1302. // sync block
  1303. {
  1304. CLock lck(_mxs); // only one thread should be in here
  1305. if ((_dwState != INetState_DONE) && (_dwState != INetState_ERROR))
  1306. {
  1307. _dwState = INetState_DONE;
  1308. }
  1309. if ( (_dwIsA == DLD_PROTOCOL_FILE)
  1310. || (_dwIsA == DLD_PROTOCOL_LOCAL)
  1311. || (_dwIsA == DLD_PROTOCOL_STREAM)
  1312. || _fHandlesRecycled
  1313. || (_HandleStateServer == HandleState_Aborted))
  1314. {
  1315. fReleaseBindInfo = TRUE;
  1316. _pCTrans->Release();
  1317. _pCTrans = NULL;
  1318. }
  1319. }
  1320. }
  1321. #if DBG == 1
  1322. if ( _BndInfo.stgmedData.tymed != TYMED_NULL )
  1323. PerfDbgLog1(tagCINet, this, "--- CINet::Stop ReleaseStgMedium (%lx)", _BndInfo.stgmedData);
  1324. #endif
  1325. if ( fReleaseBindInfo
  1326. || (_dwIsA == DLD_PROTOCOL_FILE)
  1327. || (_dwIsA == DLD_PROTOCOL_LOCAL)
  1328. || (_dwIsA == DLD_PROTOCOL_STREAM)
  1329. || _fHandlesRecycled
  1330. || (_HandleStateServer == HandleState_Aborted))
  1331. {
  1332. ReleaseBindInfo(&_BndInfo);
  1333. }
  1334. PerfDbgLog1(tagCINet, this, "-CINet::Terminate (hr:%lx)", hr);
  1335. DEBUG_LEAVE(hr);
  1336. return hr;
  1337. }
  1338. //+---------------------------------------------------------------------------
  1339. //
  1340. // Method: CINet::Suspend
  1341. //
  1342. // Synopsis:
  1343. //
  1344. // Arguments: (none)
  1345. //
  1346. // Returns:
  1347. //
  1348. // History: 10-29-1996 JohannP (Johann Posch) Created
  1349. //
  1350. // Notes:
  1351. //
  1352. //----------------------------------------------------------------------------
  1353. STDMETHODIMP CINet::Suspend()
  1354. {
  1355. DEBUG_ENTER((DBG_APP,
  1356. Hresult,
  1357. "CINet::IInternetProtocolRoot::Suspend",
  1358. "this=%#x",
  1359. this
  1360. ));
  1361. HRESULT hr = _pEmbdFilter->Suspend();
  1362. DEBUG_LEAVE(hr);
  1363. return hr;
  1364. }
  1365. STDMETHODIMP CINet::MySuspend()
  1366. {
  1367. DEBUG_ENTER((DBG_APP,
  1368. Hresult,
  1369. "CINet::MySuspend",
  1370. "this=%#x",
  1371. this
  1372. ));
  1373. PerfDbgLog(tagCINet, this, "+CINet::Suspend");
  1374. HRESULT hr = E_NOTIMPL;
  1375. PerfDbgLog1(tagCINet, this, "-CINet::Suspend (hr:%lx)", hr);
  1376. DEBUG_LEAVE(hr);
  1377. return hr;
  1378. }
  1379. //+---------------------------------------------------------------------------
  1380. //
  1381. // Method: CINet::Resume
  1382. //
  1383. // Synopsis:
  1384. //
  1385. // Arguments: (none)
  1386. //
  1387. // Returns:
  1388. //
  1389. // History: 10-29-1996 JohannP (Johann Posch) Created
  1390. //
  1391. // Notes:
  1392. //
  1393. //----------------------------------------------------------------------------
  1394. STDMETHODIMP CINet::Resume()
  1395. {
  1396. DEBUG_ENTER((DBG_APP,
  1397. Hresult,
  1398. "CINet::IInternetProtocolRoot::Resume",
  1399. "this=%#x",
  1400. this
  1401. ));
  1402. HRESULT hr = _pEmbdFilter->Resume();
  1403. DEBUG_LEAVE(hr);
  1404. return hr;
  1405. }
  1406. STDMETHODIMP CINet::MyResume()
  1407. {
  1408. DEBUG_ENTER((DBG_APP,
  1409. Hresult,
  1410. "CINet::MyResume",
  1411. "this=%#x",
  1412. this
  1413. ));
  1414. PerfDbgLog(tagCINet, this, "+CINet::Resume");
  1415. HRESULT hr = E_NOTIMPL;
  1416. PerfDbgLog1(tagCINet, this, "-CINet::Resume (hr:%lx)", hr);
  1417. DEBUG_LEAVE(hr);
  1418. return hr;
  1419. }
  1420. //+---------------------------------------------------------------------------
  1421. //
  1422. // Method: CINet::SetPriority
  1423. //
  1424. // Synopsis:
  1425. //
  1426. // Arguments: [nPriority] --
  1427. //
  1428. // Returns:
  1429. //
  1430. // History: 10-29-1996 JohannP (Johann Posch) Created
  1431. //
  1432. // Notes:
  1433. //
  1434. //----------------------------------------------------------------------------
  1435. STDMETHODIMP CINet::SetPriority(LONG nPriority)
  1436. {
  1437. DEBUG_ENTER((DBG_APP,
  1438. Hresult,
  1439. "CINet::IInternetPriority::SetPriority",
  1440. "this=%#x, %#x",
  1441. this, nPriority
  1442. ));
  1443. PerfDbgLog1(tagCINet, this, "+CINet::SetPriority (%ld)", nPriority);
  1444. HRESULT hr = S_OK;
  1445. _nPriority = nPriority;
  1446. PerfDbgLog1(tagCINet, this, "-CINet::SetPriority (hr:%lx)", hr);
  1447. DEBUG_LEAVE(hr);
  1448. return hr;
  1449. }
  1450. //+---------------------------------------------------------------------------
  1451. //
  1452. // Method: CINet::GetPriority
  1453. //
  1454. // Synopsis:
  1455. //
  1456. // Arguments: [pnPriority] --
  1457. //
  1458. // Returns:
  1459. //
  1460. // History: 10-29-1996 JohannP (Johann Posch) Created
  1461. //
  1462. // Notes:
  1463. //
  1464. //----------------------------------------------------------------------------
  1465. STDMETHODIMP CINet::GetPriority(LONG * pnPriority)
  1466. {
  1467. DEBUG_ENTER((DBG_APP,
  1468. Hresult,
  1469. "CINet::IInternetPriority::GetPriority",
  1470. "this=%#x, %#x",
  1471. this, pnPriority
  1472. ));
  1473. PerfDbgLog(tagCINet, this, "+CINet::GetPriority");
  1474. HRESULT hr = S_OK;
  1475. *pnPriority = _nPriority;
  1476. PerfDbgLog1(tagCINet, this, "-CINet::GetPriority (hr:%lx)", hr);
  1477. DEBUG_LEAVE(hr);
  1478. return hr;
  1479. }
  1480. //+---------------------------------------------------------------------------
  1481. //
  1482. // Method: CINet::Read
  1483. //
  1484. // Synopsis:
  1485. //
  1486. // Arguments: [ULONG] --
  1487. // [ULONG] --
  1488. // [pcbRead] --
  1489. //
  1490. // Returns:
  1491. //
  1492. // History: 10-29-1996 JohannP (Johann Posch) Created
  1493. //
  1494. // Notes:
  1495. //
  1496. //----------------------------------------------------------------------------
  1497. STDMETHODIMP CINet::Read(void *pv,ULONG cb,ULONG *pcbRead)
  1498. {
  1499. DEBUG_ENTER((DBG_APP,
  1500. Hresult,
  1501. "CINet::IInternetProtocol::Read",
  1502. "this=%#x, %#x, %#x, %#x",
  1503. this, pv, cb, pcbRead
  1504. ));
  1505. HRESULT hr = _pEmbdFilter->Read(pv, cb, pcbRead);
  1506. DEBUG_LEAVE(hr);
  1507. return hr;
  1508. }
  1509. STDMETHODIMP CINet::MyRead(void *pv,ULONG cb,ULONG *pcbRead)
  1510. {
  1511. DEBUG_ENTER((DBG_APP,
  1512. Hresult,
  1513. "CINet::MyRead",
  1514. "this=%#x, %#x, %#x, %#x",
  1515. this, pv, cb, pcbRead
  1516. ));
  1517. PerfDbgLog(tagCINet, this, "+CINet::Read");
  1518. HRESULT hr = NOERROR;
  1519. if(GetBindFlags() & BINDF_DIRECT_READ)
  1520. {
  1521. hr = ReadDirect((BYTE *)pv, cb, pcbRead);
  1522. }
  1523. else
  1524. {
  1525. hr = ReadDataHere((BYTE *)pv, cb, pcbRead);
  1526. }
  1527. PerfDbgLog1(tagCINet, this, "-CINet::Read (hr:%lx)", hr);
  1528. DEBUG_LEAVE(hr);
  1529. return hr;
  1530. }
  1531. //+---------------------------------------------------------------------------
  1532. //
  1533. // Method: CINet::Seek
  1534. //
  1535. // Synopsis:
  1536. //
  1537. // Arguments: [DWORD] --
  1538. // [ULARGE_INTEGER] --
  1539. // [plibNewPosition] --
  1540. //
  1541. // Returns:
  1542. //
  1543. // History: 10-29-1996 JohannP (Johann Posch) Created
  1544. //
  1545. // Notes:
  1546. //
  1547. //----------------------------------------------------------------------------
  1548. STDMETHODIMP CINet::Seek(LARGE_INTEGER dlibMove,DWORD dwOrigin,ULARGE_INTEGER *plibNewPosition)
  1549. {
  1550. DEBUG_ENTER((DBG_APP,
  1551. Hresult,
  1552. "CINet::IInternetProtocol::Seek",
  1553. "this=%#x, %#x, %#x, %#x",
  1554. this, dlibMove, dwOrigin, plibNewPosition
  1555. ));
  1556. HRESULT hr = _pEmbdFilter->Seek(dlibMove, dwOrigin, plibNewPosition);
  1557. DEBUG_LEAVE(hr);
  1558. return hr;
  1559. }
  1560. STDMETHODIMP CINet::MySeek(LARGE_INTEGER dlibMove,DWORD dwOrigin,ULARGE_INTEGER *plibNewPosition)
  1561. {
  1562. DEBUG_ENTER((DBG_APP,
  1563. Hresult,
  1564. "CINet::MySeek",
  1565. "this=%#x, %#x, %#x, %#x",
  1566. this, dlibMove, dwOrigin, plibNewPosition
  1567. ));
  1568. PerfDbgLog(tagCINet, this, "+CINet::Seek");
  1569. HRESULT hr;
  1570. hr = INetSeek(dlibMove, dwOrigin,plibNewPosition);
  1571. PerfDbgLog1(tagCINet, this, "-CINet::Seek (hr:%lx)", hr);
  1572. DEBUG_LEAVE(hr);
  1573. return hr;
  1574. }
  1575. //+---------------------------------------------------------------------------
  1576. //
  1577. // Method: CINet::LockRequest
  1578. //
  1579. // Synopsis:
  1580. //
  1581. // Arguments: [dwOptions] --
  1582. //
  1583. // Returns:
  1584. //
  1585. // History: 10-29-1996 JohannP (Johann Posch) Created
  1586. //
  1587. // Notes:
  1588. //
  1589. //----------------------------------------------------------------------------
  1590. STDMETHODIMP CINet::LockRequest(DWORD dwOptions)
  1591. {
  1592. DEBUG_ENTER((DBG_APP,
  1593. Hresult,
  1594. "CINet::IInternetProtocol::LockRequest",
  1595. "this=%#x, %#x",
  1596. this, dwOptions
  1597. ));
  1598. HRESULT hr = _pEmbdFilter->LockRequest(dwOptions);
  1599. DEBUG_LEAVE(hr);
  1600. return hr;
  1601. }
  1602. STDMETHODIMP CINet::MyLockRequest(DWORD dwOptions)
  1603. {
  1604. DEBUG_ENTER((DBG_APP,
  1605. Hresult,
  1606. "CINet::MyLockRequest",
  1607. "this=%#x, %#x",
  1608. this, dwOptions
  1609. ));
  1610. PerfDbgLog(tagCINet, this, "+CINet::LockRequest");
  1611. HRESULT hr = NOERROR;
  1612. hr = LockFile(FALSE);
  1613. PerfDbgLog1(tagCINet, this, "-CINet::LockRequest (hr:%lx)", hr);
  1614. DEBUG_LEAVE(hr);
  1615. return hr;
  1616. }
  1617. //+---------------------------------------------------------------------------
  1618. //
  1619. // Method: CINet::UnlockRequest
  1620. //
  1621. // Synopsis:
  1622. //
  1623. // Arguments: (none)
  1624. //
  1625. // Returns:
  1626. //
  1627. // History: 10-29-1996 JohannP (Johann Posch) Created
  1628. //
  1629. // Notes:
  1630. //
  1631. //----------------------------------------------------------------------------
  1632. STDMETHODIMP CINet::UnlockRequest()
  1633. {
  1634. DEBUG_ENTER((DBG_APP,
  1635. Hresult,
  1636. "CINet::IInternetProtocol::UnlockRequest",
  1637. "this=%#x",
  1638. this
  1639. ));
  1640. HRESULT hr = _pEmbdFilter->UnlockRequest();
  1641. DEBUG_LEAVE(hr);
  1642. return hr;
  1643. }
  1644. STDMETHODIMP CINet::MyUnlockRequest()
  1645. {
  1646. DEBUG_ENTER((DBG_APP,
  1647. Hresult,
  1648. "CINet::MyUnlockRequest",
  1649. "this=%#x",
  1650. this
  1651. ));
  1652. PerfDbgLog(tagCINet, this, "+CINet::UnlockRequest");
  1653. HRESULT hr = NOERROR;
  1654. TerminateRequest();
  1655. hr = UnlockFile();
  1656. PerfDbgLog1(tagCINet, this, "-CINet::UnlockRequest (hr:%lx)", hr);
  1657. DEBUG_LEAVE(hr);
  1658. return hr;
  1659. }
  1660. //+---------------------------------------------------------------------------
  1661. //
  1662. // Method: CINet::QueryOption
  1663. //
  1664. // Synopsis:
  1665. //
  1666. // Arguments: [dwOption] --
  1667. // [pBuffer] --
  1668. // [pcbBuf] --
  1669. //
  1670. // Returns:
  1671. //
  1672. // History: 4-16-96 JohannP (Johann Posch) Created
  1673. //
  1674. // Notes:
  1675. //
  1676. //----------------------------------------------------------------------------
  1677. STDMETHODIMP CINet::QueryOption(DWORD dwOption, LPVOID pBuffer, DWORD *pcbBuf)
  1678. {
  1679. DEBUG_ENTER((DBG_APP,
  1680. Hresult,
  1681. "CINet::IWininetInfo::QueryOption",
  1682. "this=%#x, %#x, %#x, %#x",
  1683. this, dwOption, pBuffer, pcbBuf
  1684. ));
  1685. PerfDbgLog1(tagCINet, this, "+CINet::QueryOptions dwOption:%ld", dwOption);
  1686. HRESULT hr;
  1687. if (!pcbBuf || (*pcbBuf == 0))
  1688. {
  1689. hr = E_INVALIDARG;
  1690. }
  1691. else if (!_hRequest)
  1692. {
  1693. *pcbBuf = 0;
  1694. hr = E_FAIL;
  1695. }
  1696. else if (dwOption == WININETINFO_OPTION_LOCK_HANDLE)
  1697. {
  1698. if ( *pcbBuf >= sizeof(HANDLE)
  1699. && InternetLockRequestFile(_hRequest, (HANDLE *)pBuffer))
  1700. {
  1701. *pcbBuf = sizeof(HANDLE);
  1702. hr = S_OK;
  1703. }
  1704. else
  1705. {
  1706. *pcbBuf = 0;
  1707. hr = E_FAIL;
  1708. }
  1709. }
  1710. else
  1711. {
  1712. if (InternetQueryOption(_hRequest, dwOption, pBuffer, pcbBuf))
  1713. {
  1714. hr = S_OK;
  1715. }
  1716. else
  1717. {
  1718. hr = S_FALSE;
  1719. }
  1720. }
  1721. PerfDbgLog2(tagCINet, this, "-CINet::QueryOptions (hr:%lx,szStr:%s)", hr, pBuffer);
  1722. DEBUG_LEAVE(hr);
  1723. return hr;
  1724. }
  1725. //+---------------------------------------------------------------------------
  1726. //
  1727. // Method: CINet::QueryInfo
  1728. //
  1729. // Synopsis:
  1730. //
  1731. // Arguments: [dwOption] --
  1732. // [pBuffer] --
  1733. // [pcbBuf] --
  1734. // [pdwFlag] --
  1735. //
  1736. // Returns:
  1737. //
  1738. // History: 4-16-96 JohannP (Johann Posch) Created
  1739. //
  1740. // Notes:
  1741. //
  1742. //----------------------------------------------------------------------------
  1743. STDMETHODIMP CINet::QueryInfo(DWORD dwOption, LPVOID pBuffer, DWORD *pcbBuf, DWORD *pdwFlags, DWORD *pdwReserved)
  1744. {
  1745. DEBUG_ENTER((DBG_APP,
  1746. Hresult,
  1747. "CINet::IWininetHttpInfo::QueryInfo",
  1748. "this=%#x, %#x, %#x, %#x, %#x, %#x",
  1749. this, dwOption, pBuffer, pcbBuf, pdwFlags, pdwReserved
  1750. ));
  1751. PerfDbgLog1(tagCINet, this, "+CINet::QueryInfo dwOption:%ld", dwOption);
  1752. HRESULT hr;
  1753. if (!pcbBuf)
  1754. {
  1755. hr = E_INVALIDARG;
  1756. }
  1757. else if (!_hRequest)
  1758. {
  1759. *pcbBuf = 0;
  1760. hr = E_FAIL;
  1761. }
  1762. else
  1763. {
  1764. if (HttpQueryInfo(_hRequest, dwOption, pBuffer, pcbBuf, pdwFlags))
  1765. {
  1766. hr = S_OK;
  1767. }
  1768. else
  1769. {
  1770. if (pBuffer && (*pcbBuf >= sizeof(HRESULT)) )
  1771. {
  1772. HRESULT *phr = (HRESULT *)pBuffer;
  1773. *phr = HRESULT_FROM_WIN32(GetLastError());
  1774. *pcbBuf = sizeof(HRESULT);
  1775. }
  1776. hr = S_FALSE;
  1777. }
  1778. }
  1779. PerfDbgLog2(tagCINet, this, "-CINet::QueryInfo (hr:%lx,szStr:%s)", hr, XDBG(pBuffer&&!hr?pBuffer:"",""));
  1780. DEBUG_LEAVE(hr);
  1781. return hr;
  1782. }
  1783. STDMETHODIMP CINet::Prepare()
  1784. {
  1785. DEBUG_ENTER((DBG_APP,
  1786. Hresult,
  1787. "CINet::IInternetThreadSwitch::Prepare",
  1788. "this=%#x",
  1789. this
  1790. ));
  1791. PerfDbgLog(tagCINet, this, "+CINet::Prepare");
  1792. HRESULT hr = NOERROR;
  1793. PerfDbgLog1(tagCINet, this, "-CINet::Prepare (hr:%lx)", hr);
  1794. DEBUG_LEAVE(hr);
  1795. return hr;
  1796. }
  1797. STDMETHODIMP CINet::Continue()
  1798. {
  1799. DEBUG_ENTER((DBG_APP,
  1800. Hresult,
  1801. "CINet::IInternetThreadSwitch::Continue",
  1802. "this=%#x",
  1803. this
  1804. ));
  1805. PerfDbgLog(tagCINet, this, "+CINet::Continue");
  1806. HRESULT hr = NOERROR;
  1807. _dwThreadID = GetCurrentThreadId();
  1808. PerfDbgLog1(tagCINet, this, "-CINet::Continue (hr:%lx)", hr);
  1809. DEBUG_LEAVE(hr);
  1810. return hr;
  1811. }
  1812. //+---------------------------------------------------------------------------
  1813. //
  1814. // Method: CINet::CINet
  1815. //
  1816. // Synopsis:
  1817. //
  1818. // Arguments: (none)
  1819. //
  1820. // Returns:
  1821. //
  1822. // History: 1-27-96 JohannP (Johann Posch) Created
  1823. //
  1824. // Notes:
  1825. //
  1826. //----------------------------------------------------------------------------
  1827. CINet::CINet(REFCLSID rclsid, IUnknown *pUnkOuter) : _CRefs(), _CRefsHandles(0), _cReadCount(0), _pclsidProtocol(rclsid), _Unknown()
  1828. {
  1829. DEBUG_ENTER((DBG_APP,
  1830. None,
  1831. "CINet::CINet",
  1832. "this=%#x, %#x, %#x",
  1833. this, &rclsid, pUnkOuter
  1834. ));
  1835. PerfDbgLog(tagCINet, this, "+CINet::CINet");
  1836. _dwEmbdFilter = NULL;
  1837. _pEmbdFilter = NULL;
  1838. _dwState = INetState_START;
  1839. _dwIsA = DLD_PROTOCOL_NONE;
  1840. _fRedirected = FALSE;
  1841. _fP2PRedirected = FALSE;
  1842. _fLocked = FALSE;
  1843. _fFilenameReported = FALSE;
  1844. _fHandlesRecycled = FALSE;
  1845. _fSendAgain = FALSE;
  1846. _fSendRequestAgain = FALSE;
  1847. _hLockHandle = NULL;
  1848. _hFile = NULL;
  1849. _dwThreadID = GetCurrentThreadId();
  1850. _fDone = 0;
  1851. _hwndAuth = NULL;
  1852. _bscf = BSCF_FIRSTDATANOTIFICATION;
  1853. _pOIBindInfo = 0;
  1854. _pszUserAgentStr = 0;
  1855. _nPriority = THREAD_PRIORITY_NORMAL;
  1856. _cbSizeLastReportData = 0;
  1857. _fForceSwitch = FALSE;
  1858. _cbAuthenticate = 0;
  1859. _cbProxyAuthenticate = 0;
  1860. _fDoSimpleRetry = FALSE;
  1861. if (!pUnkOuter)
  1862. {
  1863. pUnkOuter = &_Unknown;
  1864. }
  1865. _pUnkOuter = pUnkOuter;
  1866. _pWindow = 0;
  1867. _hServer = 0;
  1868. _hRequest = 0;
  1869. PerfDbgLog(tagCINet, this, "-CINet::CINet");
  1870. DEBUG_LEAVE(0);
  1871. }
  1872. CINet::~CINet()
  1873. {
  1874. DEBUG_ENTER((DBG_APP,
  1875. None,
  1876. "CINet::~CINet",
  1877. "this=%#x",
  1878. this
  1879. ));
  1880. delete _pwzUrl;
  1881. #if DBG == 1
  1882. _pwzUrl = NULL;
  1883. #endif
  1884. delete _pszUserAgentStr;
  1885. // release Embedded Filter
  1886. if( _pEmbdFilter )
  1887. {
  1888. CINetEmbdFilter* pEmbdFilter = _pEmbdFilter;
  1889. _pEmbdFilter = NULL;
  1890. delete pEmbdFilter;
  1891. }
  1892. PerfDbgLog(tagCINet, this, "CINet::~CINet");
  1893. DEBUG_LEAVE(0);
  1894. }
  1895. // Helper function for _pEmbdFilter sanity check:
  1896. bool CINet::IsEmbdFilterOk()
  1897. {
  1898. if(_pEmbdFilter && !::IsBadReadPtr(_pEmbdFilter, sizeof(DWORD)) && *(DWORD *)_pEmbdFilter == _dwEmbdFilter)
  1899. return true;
  1900. // Shouldn't happen, but is happening in rare cases.
  1901. // Filter got released because someone likely deleted an incorrect offset.
  1902. PProtAssert((FALSE));
  1903. PerfDbgLog(tagCINet, this, "+CINet::IsEmbdFilterOk: EmbedFilter missing, recreating.");
  1904. if(_pCTrans)
  1905. {
  1906. CLock lck(_mxs); // only one thread should be in here
  1907. // Do the check again just in case we have two threads entering:
  1908. if(_pEmbdFilter && !::IsBadReadPtr(_pEmbdFilter, sizeof(DWORD)) && *(DWORD *)_pEmbdFilter == _dwEmbdFilter)
  1909. return true;
  1910. // Release _pCTrans to compensate for the AddRef in
  1911. // the CINetEmbdFilter constructor, since the CINetEmbdFilter destructor would not have been called:
  1912. _pCTrans->Release();
  1913. // Recreate the filter here if possible:
  1914. _pEmbdFilter = new CINetEmbdFilter( this, _pCTrans );
  1915. if( !_pEmbdFilter || !_pEmbdFilter->IsInited())
  1916. {
  1917. // Something failed (deleting NULL is fine):
  1918. delete _pEmbdFilter;
  1919. goto End;
  1920. }
  1921. // For sanity checks later via IsEmbdFilterOk():
  1922. _dwEmbdFilter = *(DWORD *)_pEmbdFilter;
  1923. return true;
  1924. }
  1925. End:
  1926. PerfDbgLog(tagCINetErr, this, "+CINet::IsEmbdFilterOk: Unable to recreate EmbedFilter, possibly out of memory.");
  1927. SetINetState(INetState_ERROR);
  1928. // Null out and return false:
  1929. _pEmbdFilter = NULL;
  1930. return false;
  1931. }
  1932. //+---------------------------------------------------------------------------
  1933. //
  1934. // Method: CINet::ReportResultAndStop
  1935. //
  1936. // Synopsis: Post the termination package
  1937. //
  1938. // Arguments: [hr] --
  1939. //
  1940. // Returns:
  1941. //
  1942. // History: 1-27-96 JohannP (Johann Posch) Created
  1943. //
  1944. // Notes:
  1945. //
  1946. //----------------------------------------------------------------------------
  1947. HRESULT CINet::ReportResultAndStop(HRESULT hr, ULONG ulProgress,ULONG ulProgressMax, LPWSTR pwzStr)
  1948. {
  1949. DEBUG_ENTER((DBG_APP,
  1950. Hresult,
  1951. "CINet::ReportResultAndStop",
  1952. "this=%#x, %#x, %#x, %#x, %.80wq",
  1953. this, hr, ulProgress, ulProgressMax, pwzStr
  1954. ));
  1955. PerfDbgLog1(tagCINet, this, "+CINet::ReportResultAndStop (hr:%lx)", hr);
  1956. HRESULT hrOut = NOERROR;
  1957. BOOL fReportResult = FALSE;
  1958. BOOL fReportData = FALSE;
  1959. {
  1960. CLock lck(_mxs); // only one thread should be in here
  1961. // set the state to error and report error
  1962. // must go in queue since other messages might be ahead
  1963. if ((_dwState != INetState_DONE) && (_dwState != INetState_ERROR))
  1964. {
  1965. _hrINet = hr;
  1966. _dwState = (hr != NOERROR) ? INetState_ERROR : INetState_DONE;
  1967. if (_dwState == INetState_DONE)
  1968. {
  1969. if (ulProgress == 0)
  1970. {
  1971. ulProgress = _cbTotalBytesRead;
  1972. ulProgressMax = _cbDataSize;
  1973. }
  1974. if ( ( (ulProgress != _cbSizeLastReportData ) ||
  1975. (!ulProgress && !ulProgressMax) ) &&
  1976. ( _grfBindF & BINDF_FROMURLMON ) )
  1977. {
  1978. //
  1979. // last notification
  1980. // NOTE: we need to report data for empty page
  1981. // we might have report this data already,
  1982. // so check for the _cbSizeLastReportData
  1983. // if they are same, do not report data
  1984. // again. (this might give hard time for
  1985. // IEFeatuer handler )
  1986. //
  1987. _bscf |= BSCF_LASTDATANOTIFICATION;
  1988. fReportData = TRUE;
  1989. }
  1990. //
  1991. // HACK: for prodegy's ocx
  1992. // if we have not send out ReportData(BSCF_LAST...) and
  1993. // we are doing BindToStorage but the data has been
  1994. // reported, we have to report it again with LAST flag
  1995. // tuned on
  1996. //
  1997. if( !fReportData &&
  1998. !(_bscf & BSCF_LASTDATANOTIFICATION ) &&
  1999. !(_BndInfo.dwOptions & BINDINFO_OPTIONS_BINDTOOBJECT) )
  2000. {
  2001. // need to send out last notifiation for whatever
  2002. // client depend on it...
  2003. _bscf |= BSCF_LASTDATANOTIFICATION;
  2004. fReportData = TRUE;
  2005. }
  2006. }
  2007. else if (_dwState == INetState_ERROR)
  2008. {
  2009. SetINetState(INetState_ERROR);
  2010. }
  2011. PProtAssert((_pCTrans));
  2012. fReportResult = TRUE;
  2013. }
  2014. }
  2015. if (_pCTrans)
  2016. {
  2017. if (fReportData)
  2018. {
  2019. _cbSizeLastReportData = ulProgress;
  2020. _pEmbdFilter->ReportData(_bscf, ulProgress, ulProgressMax);
  2021. }
  2022. // teminate might have occured on ReportData
  2023. if (fReportResult && _pCTrans)
  2024. {
  2025. _pEmbdFilter->ReportResult(hr,_dwResult,pwzStr);
  2026. }
  2027. if( !fReportResult )
  2028. {
  2029. hrOut = INET_E_RESULT_DISPATCHED;
  2030. }
  2031. }
  2032. PerfDbgLog1(tagCINet, this, "-CINet::ReportResultAndStop (hrOut:%lx)", hrOut);
  2033. DEBUG_LEAVE(hrOut);
  2034. return hrOut;
  2035. }
  2036. //+---------------------------------------------------------------------------
  2037. //
  2038. // Method: CINet::ReportNotification
  2039. //
  2040. // Synopsis:
  2041. //
  2042. // Arguments: [NMsg] --
  2043. //
  2044. // Returns:
  2045. //
  2046. // History: 1-27-96 JohannP (Johann Posch) Created
  2047. //
  2048. // Notes:
  2049. //
  2050. //----------------------------------------------------------------------------
  2051. HRESULT CINet::ReportNotification(BINDSTATUS NMsg, LPCSTR szStr)
  2052. {
  2053. DEBUG_ENTER((DBG_APP,
  2054. Hresult,
  2055. "CINet::ReportNotification",
  2056. "this=%#x, %#x, %.80q",
  2057. this, NMsg, szStr
  2058. ));
  2059. PerfDbgLog1(tagCINet, this, "+CINet::ReportNotification (NMsg:%lx)", NMsg);
  2060. HRESULT hr = E_FAIL;
  2061. BOOL fReport = FALSE;
  2062. LPWSTR pwzStr = 0;
  2063. { // ssync block begin
  2064. CLock lck(_mxs); // only one thread should be in here
  2065. if ((_dwState != INetState_DONE) && (_dwState != INetState_ERROR))
  2066. {
  2067. if (szStr)
  2068. {
  2069. pwzStr = DupA2W((const LPSTR)szStr);
  2070. }
  2071. if (szStr && !pwzStr)
  2072. {
  2073. hr = E_OUTOFMEMORY;
  2074. }
  2075. else
  2076. {
  2077. fReport = TRUE;
  2078. }
  2079. }
  2080. } // sync block end
  2081. if (fReport)
  2082. {
  2083. if ( _pCTrans && IsEmbdFilterOk() )
  2084. {
  2085. hr = _pEmbdFilter->ReportProgress((ULONG)NMsg, pwzStr);
  2086. }
  2087. }
  2088. delete pwzStr;
  2089. PerfDbgLog(tagCINet, this, "-CINet::ReportNotification");
  2090. DEBUG_LEAVE(hr);
  2091. return hr;
  2092. }
  2093. HRESULT CINet::ReportNotificationW(BINDSTATUS NMsg, LPCWSTR wzStr)
  2094. {
  2095. DEBUG_ENTER((DBG_APP,
  2096. Hresult,
  2097. "CINet::ReportNotificationW",
  2098. "this=%#x, %#x, %.80q",
  2099. this, NMsg, wzStr
  2100. ));
  2101. PerfDbgLog1(tagCINet, this, "+CINet::ReportNotificationW (NMsg:%lx)", NMsg);
  2102. HRESULT hr = E_FAIL;
  2103. BOOL fReport = FALSE;
  2104. { // ssync block begin
  2105. CLock lck(_mxs); // only one thread should be in here
  2106. if ((_dwState != INetState_DONE) && (_dwState != INetState_ERROR))
  2107. fReport = TRUE;
  2108. } // sync block end
  2109. if (fReport)
  2110. {
  2111. if ( _pCTrans && _pEmbdFilter )
  2112. {
  2113. hr = _pEmbdFilter->ReportProgress((ULONG)NMsg, wzStr);
  2114. }
  2115. }
  2116. PerfDbgLog(tagCINet, this, "-CINet::ReportNotificationW");
  2117. DEBUG_LEAVE(hr);
  2118. return hr;
  2119. }
  2120. //+---------------------------------------------------------------------------
  2121. //
  2122. // Method: CINet::SetPending
  2123. //
  2124. // Synopsis:
  2125. //
  2126. // Arguments: [hrNew] --
  2127. //
  2128. // Returns:
  2129. //
  2130. // History: 3-28-96 JohannP (Johann Posch) Created
  2131. //
  2132. // Notes:
  2133. //
  2134. //----------------------------------------------------------------------------
  2135. HRESULT CINet::SetStatePending(HRESULT hrNew)
  2136. {
  2137. DEBUG_ENTER((DBG_APP,
  2138. Hresult,
  2139. "CINet::SetStatePending",
  2140. "this=%#x, %#x",
  2141. this, hrNew
  2142. ));
  2143. CLock lck(_mxs); // only one thread should be in here
  2144. HRESULT hr;
  2145. PerfDbgLog2(tagCINet, this, "CINet::SetStatePending (hrOld:%lx, hrNew:%lx)", _hrPending, hrNew);
  2146. //BUGBUG: turn this assertion on again
  2147. PProtAssert(( ( ((_hrPending != E_PENDING) && (hrNew == E_PENDING))
  2148. || ((_hrPending == E_PENDING) && (hrNew != E_PENDING))) ));
  2149. hr = _hrPending;
  2150. _hrPending = hrNew;
  2151. DEBUG_LEAVE(hr);
  2152. return hr;
  2153. }
  2154. //+---------------------------------------------------------------------------
  2155. //
  2156. // Method: CINet::GetStatePending
  2157. //
  2158. // Synopsis:
  2159. //
  2160. // Arguments: (none)
  2161. //
  2162. // Returns:
  2163. //
  2164. // History: 4-08-96 JohannP (Johann Posch) Created
  2165. //
  2166. // Notes:
  2167. //
  2168. //----------------------------------------------------------------------------
  2169. HRESULT CINet::GetStatePending()
  2170. {
  2171. DEBUG_ENTER((DBG_APP,
  2172. Hresult,
  2173. "CINet::GetStatePending",
  2174. "this=%#x",
  2175. this
  2176. ));
  2177. CLock lck(_mxs); // only one thread should be in here
  2178. //PerfDbgLog1(tagCINet, this, "CINet::GetStatePending (hr:%lx)", _hrPending);
  2179. DEBUG_LEAVE(_hrPending);
  2180. return _hrPending;
  2181. }
  2182. //+---------------------------------------------------------------------------
  2183. //
  2184. // Method: CINet::SetByteCountReadyToRead
  2185. //
  2186. // Synopsis:
  2187. //
  2188. // Arguments: [cbReadyReadNow] --
  2189. //
  2190. // Returns:
  2191. //
  2192. // History: 6-25-96 JohannP (Johann Posch) Created
  2193. //
  2194. // Notes:
  2195. //
  2196. //----------------------------------------------------------------------------
  2197. void CINet::SetByteCountReadyToRead(LONG cbReadyReadNow)
  2198. {
  2199. DEBUG_ENTER((DBG_APP,
  2200. None,
  2201. "CINet::SetByteCountReadyToRead",
  2202. "this=%#x, %#x",
  2203. this, cbReadyReadNow
  2204. ));
  2205. CLock lck(_mxs); // only one thread should be in here
  2206. PerfDbgLog3(tagCINet, this, "CINet::SetByteCountReadyToRead (cbReadReturn:%ld, cbReadyRead:%ld, cbReadyLeft:%ld)",
  2207. _cbReadyToRead, cbReadyReadNow, _cbReadyToRead + cbReadyReadNow);
  2208. _cbReadyToRead += cbReadyReadNow ;
  2209. DEBUG_LEAVE(0);
  2210. }
  2211. //+---------------------------------------------------------------------------
  2212. //
  2213. // Method: CINet::GetByteCountReadyToRead
  2214. //
  2215. // Synopsis:
  2216. //
  2217. // Arguments: (none)
  2218. //
  2219. // Returns:
  2220. //
  2221. // History: 6-25-96 JohannP (Johann Posch) Created
  2222. //
  2223. // Notes:
  2224. //
  2225. //----------------------------------------------------------------------------
  2226. ULONG CINet::GetByteCountReadyToRead()
  2227. {
  2228. DEBUG_ENTER((DBG_APP,
  2229. None,
  2230. "CINet::GetByteCountReadyToRead",
  2231. "this=%#x",
  2232. this
  2233. ));
  2234. CLock lck(_mxs); // only one thread should be in here
  2235. PerfDbgLog1(tagCINet, this, "CINet::GetByteCountReadyToRead (_cbReadyToRead:%ld)", _cbReadyToRead);
  2236. DEBUG_LEAVE(_cbReadyToRead);
  2237. return _cbReadyToRead;
  2238. }
  2239. //+---------------------------------------------------------------------------
  2240. //
  2241. // Method: CINet::SetINetState
  2242. //
  2243. // Synopsis:
  2244. //
  2245. // Arguments: [inState] --
  2246. //
  2247. // Returns:
  2248. //
  2249. // History: 2-25-96 JohannP (Johann Posch) Created
  2250. //
  2251. // Notes:
  2252. //
  2253. //----------------------------------------------------------------------------
  2254. INetState CINet::SetINetState(INetState inState)
  2255. {
  2256. DEBUG_ENTER((DBG_APP,
  2257. Dword,
  2258. "CINet::SetINetState",
  2259. "this=%#x, %#x",
  2260. this, inState
  2261. ));
  2262. CLock lck(_mxs); // only one thread should be in here
  2263. PerfDbgLog1(tagCINet, this, "+CINet::SetINetState (State:%lx)", inState);
  2264. INetState in = _INState;
  2265. _INState = inState;
  2266. PerfDbgLog1(tagCINet, this, "-CINet::SetINetState (hr:%lx)", in);
  2267. DEBUG_LEAVE(in);
  2268. return in;
  2269. }
  2270. //+---------------------------------------------------------------------------
  2271. //
  2272. // Method: CINet::GetINetState
  2273. //
  2274. // Synopsis:
  2275. //
  2276. // Arguments: (none)
  2277. //
  2278. // Returns:
  2279. //
  2280. // History: 2-25-96 JohannP (Johann Posch) Created
  2281. //
  2282. // Notes:
  2283. //
  2284. //----------------------------------------------------------------------------
  2285. INetState CINet::GetINetState()
  2286. {
  2287. DEBUG_ENTER((DBG_APP,
  2288. Dword,
  2289. "CINet::GetINetState",
  2290. "this=%#x",
  2291. this
  2292. ));
  2293. CLock lck(_mxs); // only one thread should be in here
  2294. PerfDbgLog(tagCINet, this, "+CINet::GetINetState");
  2295. INetState in = _INState;
  2296. PerfDbgLog1(tagCINet, this, "-CINet::GetINetState (hr:%lx)", in);
  2297. DEBUG_LEAVE(in);
  2298. return in;
  2299. }
  2300. //+---------------------------------------------------------------------------
  2301. //
  2302. // Method: CINet::INetAsyncStart
  2303. //
  2304. // Synopsis:
  2305. //
  2306. // Arguments:
  2307. //
  2308. // Returns:
  2309. //
  2310. // History: 1-27-96 JohannP (Johann Posch) Created
  2311. //
  2312. // Notes:
  2313. //
  2314. //----------------------------------------------------------------------------
  2315. HRESULT CINet::INetAsyncStart()
  2316. {
  2317. DEBUG_ENTER((DBG_APP,
  2318. Hresult,
  2319. "CINet::INetAsyncStart",
  2320. "this=%#x",
  2321. this
  2322. ));
  2323. PerfDbgLog(tagCINet, this, "+CINet::INetAsyncStart");
  2324. HRESULT hr = NOERROR;
  2325. BOOL fAsyncStart = FALSE;
  2326. // guard the object
  2327. PrivAddRef();
  2328. if (fAsyncStart)
  2329. {
  2330. // post notification for next step
  2331. SetINetState(INetState_START);
  2332. TransitState(INetState_START);
  2333. }
  2334. else
  2335. {
  2336. hr = INetAsyncOpen();
  2337. }
  2338. if (_hrError != INET_E_OK)
  2339. {
  2340. if (hr != S_OK && hr != E_PENDING && hr != INET_E_DONE)
  2341. {
  2342. PProtAssert(( (hr >= INET_E_ERROR_FIRST && hr <= INET_E_ERROR_LAST)
  2343. ||(hr == E_OUTOFMEMORY)
  2344. ||(hr == E_ABORT)
  2345. ));
  2346. ReportResultAndStop(hr);
  2347. }
  2348. else
  2349. {
  2350. // he will do inetdone notifications
  2351. ReportResultAndStop(NOERROR);
  2352. }
  2353. }
  2354. PrivRelease();
  2355. PerfDbgLog1(tagCINet, this, "-CINet::INetAsyncStart (hr:%lx)", hr);
  2356. DEBUG_LEAVE(hr);
  2357. return hr;
  2358. }
  2359. //+---------------------------------------------------------------------------
  2360. //
  2361. // Method: CINet::OnINetStart
  2362. //
  2363. // Synopsis:
  2364. //
  2365. // Arguments: (none)
  2366. //
  2367. // Returns:
  2368. //
  2369. // History: 1-27-96 JohannP (Johann Posch) Created
  2370. //
  2371. // Notes:
  2372. //
  2373. //----------------------------------------------------------------------------
  2374. HRESULT CINet::OnINetStart()
  2375. {
  2376. DEBUG_ENTER((DBG_APP,
  2377. Hresult,
  2378. "CINet::OnINetStart",
  2379. "this=%#x",
  2380. this
  2381. ));
  2382. HRESULT hr;
  2383. PerfDbgLog(tagCINet, this, "+CINet::OnINetStart");
  2384. // nothing to do - just call
  2385. hr = INetAsyncOpen();
  2386. PerfDbgLog1(tagCINet, this, "-CINet::OnINetStart (hr:%lx)", hr);
  2387. DEBUG_LEAVE(hr);
  2388. return hr;
  2389. }
  2390. //+---------------------------------------------------------------------------
  2391. //
  2392. // Method: CINet::INetAsyncOpen
  2393. //
  2394. // Synopsis:
  2395. //
  2396. // Arguments: (none)
  2397. //
  2398. // Returns:
  2399. //
  2400. // History: 1-27-96 JohannP (Johann Posch) Created
  2401. //
  2402. // Notes:
  2403. //
  2404. //----------------------------------------------------------------------------
  2405. HRESULT CINet::INetAsyncOpen()
  2406. {
  2407. DEBUG_ENTER((DBG_APP,
  2408. Hresult,
  2409. "CINet::INetAsyncOpen",
  2410. "this=%#x",
  2411. this
  2412. ));
  2413. PerfDbgLog(tagCINet, this, "+CINet::INetAsyncOpen");
  2414. PProtAssert((GetStatePending() == NOERROR));
  2415. DWORD dwFlags = INTERNET_FLAG_ASYNC;
  2416. DWORD dwBindF = 0;
  2417. HRESULT hr = NOERROR;
  2418. if (g_hSession == NULL)
  2419. {
  2420. // Only 1 thread should be in here, this is to protect
  2421. // two global variables g_hSession and g_pszUserAgentString
  2422. {
  2423. CLock lck(g_mxsSession);
  2424. if( g_hSession == NULL )
  2425. {
  2426. SetINetState(INetState_OPEN_REQUEST);
  2427. PerfDbgLog1(tagCINet, this, "___ INetAysncOpen calling InternetOpen %ld", GetTickCount());
  2428. SetStatePending(E_PENDING);
  2429. g_hSession = InternetOpen(
  2430. GetUserAgentString()
  2431. , INTERNET_OPEN_TYPE_PRECONFIG
  2432. , NULL
  2433. , NULL
  2434. , dwFlags);
  2435. PerfDbgLog1(tagCINet, this, "___ INetAysncOpen done InternetOpen %ld", GetTickCount());
  2436. if (g_hSession == NULL)
  2437. {
  2438. dwLstError = GetLastError();
  2439. if (dwLstError == ERROR_IO_PENDING)
  2440. {
  2441. hr = E_PENDING;
  2442. }
  2443. else
  2444. {
  2445. SetStatePending(NOERROR);
  2446. hr = _hrError = INET_E_NO_SESSION;
  2447. SetBindResult(dwLstError, hr);
  2448. }
  2449. }
  2450. else
  2451. {
  2452. if (g_pszUserAgentString)
  2453. {
  2454. // Open was successful, so we don't need the replacement
  2455. // User Agent string anymore.
  2456. delete g_pszUserAgentString;
  2457. g_pszUserAgentString = NULL;
  2458. }
  2459. SetStatePending(NOERROR);
  2460. InternetSetStatusCallbackA(g_hSession, CINetCallback);
  2461. hr = INetAsyncConnect();
  2462. }
  2463. }
  2464. else
  2465. {
  2466. hr = INetAsyncConnect();
  2467. }
  2468. } // single access block
  2469. }
  2470. else
  2471. {
  2472. hr = INetAsyncConnect();
  2473. }
  2474. PerfDbgLog1(tagCINet, this, "-CINet::INetAsyncOpen (hr:%lx)", hr);
  2475. DEBUG_LEAVE(hr);
  2476. return hr;
  2477. }
  2478. //+---------------------------------------------------------------------------
  2479. //
  2480. // Method: CINet::OnINetAsyncOpen
  2481. //
  2482. // Synopsis:
  2483. //
  2484. // Arguments: [dwResult] --
  2485. //
  2486. // Returns:
  2487. //
  2488. // History: 1-27-96 JohannP (Johann Posch) Created
  2489. //
  2490. // Notes:
  2491. //
  2492. //----------------------------------------------------------------------------
  2493. HRESULT CINet::OnINetAsyncOpen(DWORD_PTR dwResult)
  2494. {
  2495. DEBUG_ENTER((DBG_APP,
  2496. Hresult,
  2497. "CINet::OnINetAsyncOpen",
  2498. "this=%#x, %#x",
  2499. this, dwResult
  2500. ));
  2501. PerfDbgLog(tagCINet, this, "+CINet::OnINetAsyncOpen");
  2502. HRESULT hr = NOERROR;
  2503. PProtAssert((GetStatePending() == E_PENDING));
  2504. // set state to normal - no pending transaction
  2505. SetStatePending(NOERROR);
  2506. if (dwResult)
  2507. {
  2508. // set the handle and the callback
  2509. g_hSession = (HINTERNET) dwResult;
  2510. InternetSetStatusCallbackA(g_hSession, CINetCallback);
  2511. }
  2512. // notification for next request
  2513. TransitState(INetState_OPEN_REQUEST);
  2514. PerfDbgLog1(tagCINet, this, "-CINet::OnINetAsyncOpen (hr:%lx)", hr);
  2515. DEBUG_LEAVE(hr);
  2516. return hr;
  2517. }
  2518. //+---------------------------------------------------------------------------
  2519. //
  2520. // Method: CINet::INetAsyncConnect
  2521. //
  2522. // Synopsis:
  2523. //
  2524. // Arguments: (none)
  2525. //
  2526. // Returns:
  2527. //
  2528. // History: 1-27-96 JohannP (Johann Posch) Created
  2529. //
  2530. // Notes:
  2531. //
  2532. //----------------------------------------------------------------------------
  2533. HRESULT CINet::INetAsyncConnect()
  2534. {
  2535. DEBUG_ENTER((DBG_APP,
  2536. Hresult,
  2537. "CINet::INetAsyncConnect",
  2538. "this=%#x",
  2539. this
  2540. ));
  2541. PerfDbgLog(tagCINet, this, "+CINet::INetAsyncConnect");
  2542. PProtAssert((GetStatePending() == NOERROR));
  2543. HRESULT hr = NOERROR;
  2544. BOOL fRestarted;
  2545. DWORD dwBindF = 0;
  2546. DWORD dwService = INTERNET_SERVICE_HTTP;
  2547. // get the open flags
  2548. dwBindF = GetBindFlags();
  2549. if (dwBindF & BINDF_GETNEWESTVERSION)
  2550. {
  2551. _dwOpenFlags |= INTERNET_FLAG_RELOAD;
  2552. PerfDbgLog1(tagCINet, this, "***CINet::****RELOAD***** %lx", dwBindF);
  2553. }
  2554. else
  2555. {
  2556. PerfDbgLog1(tagCINet, this, "---CINet::----NO-RELOAD %lx --", dwBindF);
  2557. }
  2558. if (dwBindF & BINDF_NOWRITECACHE)
  2559. {
  2560. _dwOpenFlags |= INTERNET_FLAG_DONT_CACHE ;
  2561. }
  2562. if (dwBindF & BINDF_NEEDFILE)
  2563. {
  2564. PerfDbgLog(tagCINet, this, "CINet::INetAsyncConnect: turn on: INTERNET_FLAG_NEED_FILE");
  2565. _dwOpenFlags |= INTERNET_FLAG_NEED_FILE;
  2566. }
  2567. if (dwBindF & (BINDF_NO_UI | BINDF_SILENTOPERATION))
  2568. {
  2569. _dwOpenFlags |= INTERNET_FLAG_NO_UI;
  2570. }
  2571. // BUGBUG OFFLINE, RELOAD, RESYNCHRONIZE and HYPERLINK are mutually
  2572. // exclusive. But inside wininet there is priority, so
  2573. // the priority is OFFLINE, RELOAD, RESYNCHRONIZE, HYPERLINK in that order
  2574. if (dwBindF & BINDF_RESYNCHRONIZE)
  2575. {
  2576. // caller asking to do if-modified-since
  2577. _dwOpenFlags |= INTERNET_FLAG_RESYNCHRONIZE;
  2578. }
  2579. if (dwBindF & BINDF_HYPERLINK)
  2580. {
  2581. // caller says this is a hyperlink access
  2582. _dwOpenFlags |= INTERNET_FLAG_HYPERLINK;
  2583. }
  2584. if (dwBindF & BINDF_FORMS_SUBMIT)
  2585. {
  2586. // caller says this is a forms submit.
  2587. _dwOpenFlags |= INTERNET_FLAG_FORMS_SUBMIT;
  2588. }
  2589. if (dwBindF & BINDF_OFFLINEOPERATION )
  2590. {
  2591. _dwOpenFlags |= INTERNET_FLAG_OFFLINE;
  2592. }
  2593. // connect flags
  2594. if (dwBindF & BINDF_OFFLINEOPERATION )
  2595. {
  2596. _dwConnectFlags |= INTERNET_FLAG_OFFLINE;
  2597. }
  2598. if (dwBindF & BINDF_PRAGMA_NO_CACHE )
  2599. {
  2600. _dwOpenFlags |= INTERNET_FLAG_PRAGMA_NOCACHE;
  2601. }
  2602. if( dwBindF & BINDF_GETFROMCACHE_IF_NET_FAIL)
  2603. {
  2604. _dwOpenFlags |= INTERNET_FLAG_CACHE_IF_NET_FAIL;
  2605. }
  2606. if( dwBindF & BINDF_FWD_BACK )
  2607. {
  2608. _dwOpenFlags |= INTERNET_FLAG_FWD_BACK;
  2609. }
  2610. // additional wininet flags are passed with bindinfo
  2611. if( _BndInfo.dwOptions == BINDINFO_OPTIONS_WININETFLAG )
  2612. {
  2613. _dwOpenFlags |= _BndInfo.dwOptionsFlags;
  2614. }
  2615. SetINetState(INetState_CONNECT_REQUEST);
  2616. PrivAddRef(TRUE);
  2617. _HandleStateServer = HandleState_Pending;
  2618. SetStatePending(E_PENDING);
  2619. HINTERNET hServerTmp = InternetConnect(
  2620. g_hSession, // hInternetSession
  2621. GetServerName(), // lpszServerName
  2622. _ipPort, // nServerPort
  2623. (_pszUserName[0])?_pszUserName:NULL, // lpszUserName
  2624. (_pszPassword[0])?_pszPassword:NULL, // lpszPassword
  2625. dwService, // INTERNET_SERVICE_HTTP
  2626. _dwConnectFlags, // dwFlags
  2627. (DWORD_PTR) this
  2628. );
  2629. //
  2630. // Note: do not remove this state setting here!
  2631. // there is a timing window - needs to
  2632. // be fixed in wininet/urlmon!!!
  2633. SetINetState(INetState_CONNECT_REQUEST);
  2634. if ( hServerTmp == 0)
  2635. {
  2636. dwLstError = GetLastError();
  2637. if (dwLstError == ERROR_IO_PENDING)
  2638. {
  2639. // wait async for the handle
  2640. hr = E_PENDING;
  2641. }
  2642. else
  2643. {
  2644. PrivRelease(TRUE);
  2645. SetStatePending(NOERROR);
  2646. hr = _hrError = INET_E_CANNOT_CONNECT;
  2647. SetBindResult(dwLstError, hr);
  2648. }
  2649. }
  2650. else
  2651. {
  2652. _hServer = hServerTmp;
  2653. SetStatePending(NOERROR);
  2654. // wininet holds on to CINet - Release called on the callback on close handle
  2655. _HandleStateServer = HandleState_Initialized;
  2656. PerfDbgLog1(tagCINet, this, "=== CINet::INetAsyncConnect (hServer:%lx)", _hServer);
  2657. PProtAssert((_hServer));
  2658. hr = INetAsyncOpenRequest();
  2659. }
  2660. PerfDbgLog1(tagCINet, this, "-CINet::INetAsyncConnect (hr:%lx)", hr);
  2661. DEBUG_LEAVE(hr);
  2662. return hr;
  2663. }
  2664. //+---------------------------------------------------------------------------
  2665. //
  2666. // Method: CINet::OnINetConnect
  2667. //
  2668. // Synopsis:
  2669. //
  2670. // Arguments: [dwResult] --
  2671. //
  2672. // Returns:
  2673. //
  2674. // History: 1-27-96 JohannP (Johann Posch) Created
  2675. //
  2676. // Notes:
  2677. //
  2678. //----------------------------------------------------------------------------
  2679. HRESULT CINet::OnINetConnect(DWORD_PTR dwResult)
  2680. {
  2681. DEBUG_ENTER((DBG_APP,
  2682. Hresult,
  2683. "CINet::OnINetConnect",
  2684. "this=%#x, %#x",
  2685. this, dwResult
  2686. ));
  2687. PerfDbgLog(tagCINet, this, "+CINet::OnINetConnect");
  2688. HRESULT hr = NOERROR;
  2689. PProtAssert((GetStatePending() == E_PENDING));
  2690. // set state to normal - no pending transaction
  2691. SetStatePending(NOERROR);
  2692. TransAssert((_hServer == 0));
  2693. if (dwResult)
  2694. {
  2695. CLock lck(_mxs); // only one thread should be in here
  2696. if (_HandleStateServer == HandleState_Pending)
  2697. {
  2698. TransAssert((_hServer == 0));
  2699. // set the server handle
  2700. _HandleStateServer = HandleState_Initialized;
  2701. _hServer = (HANDLE)dwResult;
  2702. }
  2703. // wininet holds on to CINet - Release called on the callback on close handle
  2704. PerfDbgLog1(tagCINet, this, "=== CINet::OnINetConnect (hServer:%lx)", _hServer);
  2705. }
  2706. if (_hServer)
  2707. {
  2708. TransitState(INetState_CONNECT_REQUEST);
  2709. }
  2710. else
  2711. {
  2712. PProtAssert((_HandleStateServer == HandleState_Aborted));
  2713. PrivRelease(TRUE);
  2714. }
  2715. PerfDbgLog1(tagCINet, this, "-CINet::OnINetConnect (hr:%lx)", hr);
  2716. DEBUG_LEAVE(hr);
  2717. return hr;
  2718. }
  2719. //+---------------------------------------------------------------------------
  2720. //
  2721. // Method: CINet::INetAsyncOpenRequest
  2722. //
  2723. // Synopsis:
  2724. //
  2725. // Arguments: (none)
  2726. //
  2727. // Returns:
  2728. //
  2729. // History: 1-27-96 JohannP (Johann Posch) Created
  2730. //
  2731. // Notes:
  2732. //
  2733. //----------------------------------------------------------------------------
  2734. HRESULT CINet::INetAsyncOpenRequest()
  2735. {
  2736. DEBUG_ENTER((DBG_APP,
  2737. Hresult,
  2738. "CINet::INetAsyncOpenRequest",
  2739. "this=%#x",
  2740. this
  2741. ));
  2742. PerfDbgLog(tagCINet, this, "+CINet::INetAsyncOpenRequest");
  2743. HRESULT hr = E_FAIL;
  2744. PerfDbgLog1(tagCINet, this, "-CINet::INetAsyncOpenRequest (hr:%lx)", hr);
  2745. DEBUG_LEAVE(hr);
  2746. return hr;
  2747. }
  2748. //+---------------------------------------------------------------------------
  2749. //
  2750. // Method: CINet::OnINetOpenRequest
  2751. //
  2752. // Synopsis:
  2753. //
  2754. // Arguments: [dwResult] --
  2755. //
  2756. // Returns:
  2757. //
  2758. // History: 1-27-96 JohannP (Johann Posch) Created
  2759. //
  2760. // Notes:
  2761. //
  2762. //----------------------------------------------------------------------------
  2763. HRESULT CINet::OnINetOpenRequest(DWORD_PTR dwResult)
  2764. {
  2765. DEBUG_ENTER((DBG_APP,
  2766. Hresult,
  2767. "CINet::OnINetOpenRequest",
  2768. "this=%#x, %#x",
  2769. this, dwResult
  2770. ));
  2771. PerfDbgLog1(tagCINet, this, "+CINet::OnINetOpenRequest (dwResult:%lx)", dwResult);
  2772. HRESULT hr = NOERROR;
  2773. PProtAssert((GetStatePending() == E_PENDING));
  2774. // set state to normal - no pending transaction
  2775. SetStatePending(NOERROR);
  2776. TransAssert((_hRequest == 0));
  2777. if (dwResult)
  2778. {
  2779. CLock lck(_mxs); // only one thread should be in here
  2780. if (_HandleStateRequest == HandleState_Pending)
  2781. {
  2782. // set the request handle
  2783. _HandleStateRequest = HandleState_Initialized;
  2784. _hRequest = (HANDLE)dwResult;
  2785. PProtAssert((_hServer != _hRequest));
  2786. }
  2787. }
  2788. if (_hRequest)
  2789. {
  2790. if (_fUTF8hack)
  2791. {
  2792. DWORD dwSendUTF8 = 1;
  2793. InternetSetOption(_hRequest, INTERNET_OPTION_SEND_UTF8_SERVERNAME_TO_PROXY, &dwSendUTF8, sizeof(DWORD));
  2794. }
  2795. hr = INetAsyncSendRequest();
  2796. }
  2797. else
  2798. {
  2799. PProtAssert((_HandleStateRequest == HandleState_Aborted));
  2800. PrivRelease(TRUE);
  2801. }
  2802. PerfDbgLog1(tagCINet, this, "-CINet::OnINetOpenRequest (hr:%lx)", hr);
  2803. DEBUG_LEAVE(hr);
  2804. return hr;
  2805. }
  2806. //+---------------------------------------------------------------------------
  2807. //
  2808. // Method: CINet::INetAsyncSendRequest
  2809. //
  2810. // Synopsis:
  2811. //
  2812. // Arguments: (none)
  2813. //
  2814. // Returns:
  2815. //
  2816. // History: 1-27-96 JohannP (Johann Posch) Created
  2817. //
  2818. // Notes:
  2819. //
  2820. //----------------------------------------------------------------------------
  2821. HRESULT CINet::INetAsyncSendRequest()
  2822. {
  2823. DEBUG_ENTER((DBG_APP,
  2824. Hresult,
  2825. "CINet::INetAsyncSendRequest",
  2826. "this=%#x",
  2827. this
  2828. ));
  2829. PerfDbgLog(tagCINet, this, "+CINet::INetAsyncSendRequest");
  2830. HRESULT hr = E_FAIL;
  2831. PerfDbgLog1(tagCINet, this, "-CINet::INetAsyncSendRequest (hr:%lx)", hr);
  2832. DEBUG_LEAVE(hr);
  2833. return hr;
  2834. }
  2835. //+---------------------------------------------------------------------------
  2836. //
  2837. // Method: CINet::OnINetSendRequest
  2838. //
  2839. // Synopsis:
  2840. //
  2841. // Arguments: [dwResult] --
  2842. //
  2843. // Returns:
  2844. //
  2845. // History: 1-27-96 JohannP (Johann Posch) Created
  2846. //
  2847. // Notes:
  2848. //
  2849. //----------------------------------------------------------------------------
  2850. HRESULT CINet::OnINetSendRequest( DWORD dwResult)
  2851. {
  2852. DEBUG_ENTER((DBG_APP,
  2853. Hresult,
  2854. "CINet::OnINetSendRequest",
  2855. "this=%#x, %#x",
  2856. this, dwResult
  2857. ));
  2858. PerfDbgLog(tagCINet, this, "+CINet::OnINetSendRequest");
  2859. HRESULT hr = NOERROR;
  2860. PProtAssert((GetStatePending() == E_PENDING));
  2861. // set state to normal - no pending transaction
  2862. SetStatePending(NOERROR);
  2863. _dwSendRequestResult = dwResult;
  2864. _lpvExtraSendRequestResult = NULL;
  2865. if( dwResult == ERROR_INTERNET_FORCE_RETRY )
  2866. {
  2867. PerfDbgLog(tagCINet, this, " --dwResult = FORCE_RETRY! ");
  2868. _fSendRequestAgain = TRUE;
  2869. }
  2870. if (OperationOnAparmentThread(INetState_SEND_REQUEST))
  2871. {
  2872. // query for content-encoding header, if we find one,
  2873. // we will have to force TransitState to do thread switching
  2874. // since the compression filter can not be loaded on worker
  2875. // thread
  2876. char szEncType[SZMIMESIZE_MAX] = "";
  2877. DWORD cbLen = sizeof(szEncType);
  2878. if( _hRequest &&
  2879. HttpQueryInfo(_hRequest, HTTP_QUERY_CONTENT_ENCODING,
  2880. szEncType, &cbLen, NULL) )
  2881. {
  2882. if( cbLen && szEncType[0] )
  2883. _fForceSwitch = TRUE;
  2884. }
  2885. // if sec problem shows up on UI thread, we need to
  2886. // force switch
  2887. switch(_dwSendRequestResult)
  2888. {
  2889. case ERROR_INTERNET_SEC_CERT_DATE_INVALID :
  2890. case ERROR_INTERNET_SEC_CERT_CN_INVALID :
  2891. case ERROR_INTERNET_HTTP_TO_HTTPS_ON_REDIR :
  2892. case ERROR_INTERNET_HTTPS_TO_HTTP_ON_REDIR :
  2893. case ERROR_INTERNET_HTTPS_HTTP_SUBMIT_REDIR :
  2894. case ERROR_HTTP_REDIRECT_NEEDS_CONFIRMATION :
  2895. case ERROR_INTERNET_INVALID_CA :
  2896. case ERROR_INTERNET_CLIENT_AUTH_CERT_NEEDED :
  2897. case ERROR_INTERNET_FORTEZZA_LOGIN_NEEDED :
  2898. case ERROR_INTERNET_FORCE_RETRY :
  2899. case ERROR_INTERNET_SEC_CERT_ERRORS :
  2900. case ERROR_INTERNET_SEC_CERT_REV_FAILED :
  2901. case ERROR_INTERNET_SEC_CERT_REVOKED :
  2902. _fForceSwitch = TRUE;
  2903. }
  2904. TransitState(INetState_SEND_REQUEST);
  2905. }
  2906. else if (!IsUpLoad())
  2907. {
  2908. hr = INetQueryInfo();
  2909. }
  2910. else
  2911. {
  2912. if( _fSendRequestAgain )
  2913. {
  2914. _fCompleted = FALSE;
  2915. _fSendAgain = TRUE;
  2916. _fSendRequestAgain = FALSE;
  2917. hr = INetAsyncSendRequest();
  2918. }
  2919. }
  2920. PerfDbgLog1(tagCINet, this, "-CINet::OnINetSendRequest (hr:%lx)", hr);
  2921. DEBUG_LEAVE(hr);
  2922. return hr;
  2923. }
  2924. //+---------------------------------------------------------------------------
  2925. //
  2926. // Method: CINet::OnINetSuspendSendRequest
  2927. //
  2928. // Synopsis: called on a wininet callback to indicate the suspentition
  2929. // of request processing until UI is displayed to the user.
  2930. //
  2931. // Arguments: [dwResult] -- error code to generate dialog for
  2932. // [lpvExtraResult] -- extra void pointer used pass dialog specific data
  2933. //
  2934. // Returns:
  2935. //
  2936. // History: 5-24-98 ArthurBi (Arthur Bierer) Created
  2937. //
  2938. // Notes:
  2939. //
  2940. //----------------------------------------------------------------------------
  2941. HRESULT CINet::OnINetSuspendSendRequest(DWORD dwResult, LPVOID lpvExtraResult)
  2942. {
  2943. DEBUG_ENTER((DBG_APP,
  2944. Hresult,
  2945. "CINet::OnINetSuspendSendRequest",
  2946. "this=%#x, %#x, %#x",
  2947. this, dwResult, lpvExtraResult
  2948. ));
  2949. PerfDbgLog(tagCINet, this, "+CINet::OnINetSuspendSendRequest");
  2950. HRESULT hr = NOERROR;
  2951. PProtAssert((GetStatePending() == E_PENDING));
  2952. // set state to normal - no pending transaction
  2953. SetStatePending(NOERROR);
  2954. _dwSendRequestResult = dwResult;
  2955. _lpvExtraSendRequestResult = lpvExtraResult;
  2956. //if (OperationOnAparmentThread(INetState_SEND_REQUEST))
  2957. // even though we're not doing auth, we need to do UI
  2958. _hrINet = INET_E_AUTHENTICATION_REQUIRED;
  2959. TransitState(INetState_DISPLAY_UI, TRUE);
  2960. PerfDbgLog1(tagCINet, this, "-CINet::OnINetSuspendSendRequest (hr:%lx)", hr);
  2961. DEBUG_LEAVE(hr);
  2962. return hr;
  2963. }
  2964. //+---------------------------------------------------------------------------
  2965. //
  2966. // Method: CINet::INetStateChange
  2967. //
  2968. // Synopsis: called on the apartment thread
  2969. //
  2970. // Arguments: (none)
  2971. //
  2972. // Returns:
  2973. //
  2974. // History: 1-22-1997 JohannP (Johann Posch) Created
  2975. //
  2976. // Notes:
  2977. //
  2978. //----------------------------------------------------------------------------
  2979. HRESULT CINet::INetStateChange()
  2980. {
  2981. DEBUG_ENTER((DBG_APP,
  2982. Hresult,
  2983. "CINet::INetStateChange",
  2984. "this=%#x",
  2985. this
  2986. ));
  2987. PerfDbgLog(tagCINet, this, "+CINet::INetStateChange");
  2988. HRESULT hr = NOERROR;
  2989. g_cInetState.HandleState();
  2990. PerfDbgLog1(tagCINet, this, "-CINet::INetStateChange (hr:%lx)", hr);
  2991. DEBUG_LEAVE(hr);
  2992. return hr;
  2993. }
  2994. //+---------------------------------------------------------------------------
  2995. //
  2996. // Method: CINet::OnINetStateChange
  2997. //
  2998. // Synopsis: called on the wininet worker thread whenever the
  2999. // wininet state changes
  3000. //
  3001. // Arguments: [dwResult] --
  3002. //
  3003. // Returns:
  3004. //
  3005. // History: 1-22-1997 JohannP (Johann Posch) Created
  3006. //
  3007. // Notes:
  3008. //
  3009. //----------------------------------------------------------------------------
  3010. HRESULT CINet::OnINetStateChange( DWORD dwResult)
  3011. {
  3012. DEBUG_ENTER((DBG_APP,
  3013. Hresult,
  3014. "CINet::OnINetStateChange",
  3015. "this=%#x, %#x",
  3016. this, dwResult
  3017. ));
  3018. PerfDbgLog(tagCINet, this, "+CINet::OnINetStateChange");
  3019. HRESULT hr = NOERROR;
  3020. // set the new state and ping the apartment thread
  3021. g_cInetState.SetState(dwResult);
  3022. TransitState(INetState_INETSTATE_CHANGE);
  3023. PerfDbgLog1(tagCINet, this, "-CINet::OnINetStateChange (hr:%lx)", hr);
  3024. DEBUG_LEAVE(hr);
  3025. return hr;
  3026. }
  3027. //+---------------------------------------------------------------------------
  3028. //
  3029. // Method: CINet::INetQueryInfo
  3030. //
  3031. // Synopsis:
  3032. //
  3033. // Arguments: (none)
  3034. //
  3035. // Returns:
  3036. //
  3037. // History: 1-27-96 JohannP (Johann Posch) Created
  3038. //
  3039. // Notes:
  3040. //
  3041. //----------------------------------------------------------------------------
  3042. HRESULT CINet::INetQueryInfo()
  3043. {
  3044. DEBUG_ENTER((DBG_APP,
  3045. Hresult,
  3046. "CINet::INetQueryInfo",
  3047. "this=%#x",
  3048. this
  3049. ));
  3050. PerfDbgLog(tagCINet, this, "+CINet::INetQueryInfo");
  3051. HRESULT hr = NOERROR;
  3052. // Here we check if we need to do redirection, or
  3053. // whether authentication is needed etc.
  3054. if (!IsUpLoad())
  3055. {
  3056. hr = QueryInfoOnResponse();
  3057. }
  3058. if (hr == NOERROR)
  3059. {
  3060. // read more data from wininet
  3061. hr = INetRead();
  3062. }
  3063. else if (hr == S_FALSE)
  3064. {
  3065. // S_FALSE means successful redirecting occured
  3066. hr = NOERROR;
  3067. }
  3068. if (_hrError != INET_E_OK)
  3069. {
  3070. // we need to terminate here
  3071. ReportResultAndStop(hr);
  3072. }
  3073. PerfDbgLog1(tagCINet, this, "-CINet::INetQueryInfo (hr:%lx)", hr);
  3074. DEBUG_LEAVE(hr);
  3075. return hr;
  3076. }
  3077. //+---------------------------------------------------------------------------
  3078. //
  3079. // Method: CINet::OnINetRead
  3080. //
  3081. // Synopsis:
  3082. //
  3083. // Arguments: [dwResult] --
  3084. //
  3085. // Returns:
  3086. //
  3087. // History: 1-27-96 JohannP (Johann Posch) Created
  3088. //
  3089. // Notes:
  3090. //
  3091. //----------------------------------------------------------------------------
  3092. HRESULT CINet::OnINetRead(DWORD_PTR dwResult)
  3093. {
  3094. DEBUG_ENTER((DBG_APP,
  3095. Hresult,
  3096. "CINet::OnINetRead",
  3097. "this=%#x, %#x",
  3098. this, dwResult
  3099. ));
  3100. PerfDbgLog(tagCINet, this, "+CINet::OnINetRead");
  3101. HRESULT hr = NOERROR;
  3102. PProtAssert((GetStatePending() == E_PENDING));
  3103. // set state to normal - no pending transaction
  3104. SetStatePending(NOERROR);
  3105. if (OperationOnAparmentThread(INetState_SEND_REQUEST))
  3106. {
  3107. TransitState(INetState_READ);
  3108. }
  3109. else
  3110. {
  3111. hr = INetRead();
  3112. }
  3113. PerfDbgLog1(tagCINet, this, "-CINet::OnINetRead (hr:%lx)", hr);
  3114. DEBUG_LEAVE(hr);
  3115. return hr;
  3116. }
  3117. //+---------------------------------------------------------------------------
  3118. //
  3119. // Method: CINet::INetRead
  3120. //
  3121. // Synopsis:
  3122. //
  3123. // Arguments: (none)
  3124. //
  3125. // Returns:
  3126. //
  3127. // History: 1-27-96 JohannP (Johann Posch) Created
  3128. //
  3129. // Notes:
  3130. //
  3131. //----------------------------------------------------------------------------
  3132. HRESULT CINet::INetRead()
  3133. {
  3134. DEBUG_ENTER((DBG_APP,
  3135. Hresult,
  3136. "CINet::INetRead",
  3137. "this=%#x",
  3138. this
  3139. ));
  3140. PerfDbgLog(tagCINet, this, "+CINet::INetRead");
  3141. HRESULT hr = NOERROR;
  3142. if (IsUpLoad())
  3143. {
  3144. hr = INetWrite();
  3145. }
  3146. else if(GetBindFlags() & BINDF_DIRECT_READ)
  3147. {
  3148. hr = INetReadDirect();
  3149. }
  3150. else
  3151. {
  3152. // this is the no-copy case
  3153. // read data to users buffer
  3154. hr = INetDataAvailable();
  3155. }
  3156. if (_hrError != INET_E_OK)
  3157. {
  3158. // we need to terminate here
  3159. ReportResultAndStop((_hrError == INET_E_DONE) ? NOERROR : _hrError);
  3160. }
  3161. PerfDbgLog1(tagCINet, this, "-CINet::INetRead (hr:%lx)", hr);
  3162. DEBUG_LEAVE(hr);
  3163. return hr;
  3164. }
  3165. //+---------------------------------------------------------------------------
  3166. //
  3167. // Method: CINet::INetwrite
  3168. //
  3169. // Synopsis:
  3170. //
  3171. // Arguments: (none)
  3172. //
  3173. // Returns:
  3174. //
  3175. // History: 1-27-96 JohannP (Johann Posch) Created
  3176. //
  3177. // Notes:
  3178. //
  3179. //----------------------------------------------------------------------------
  3180. HRESULT CINet::INetWrite()
  3181. {
  3182. DEBUG_ENTER((DBG_APP,
  3183. Hresult,
  3184. "CINet::INetWrite",
  3185. "this=%#x",
  3186. this
  3187. ));
  3188. HRESULT hr = E_FAIL;
  3189. TransAssert((FALSE && "HAS TO BE OVERWRITTEN"));
  3190. DEBUG_LEAVE(hr);
  3191. return hr;
  3192. }
  3193. #define COOKIES_BLOCKED_STRING "CookiesBlocked"
  3194. BINDSTATUS BindStatusFromCookieAction(DWORD dwCookieAction)
  3195. {
  3196. BINDSTATUS nMsg;
  3197. switch(dwCookieAction)
  3198. {
  3199. case COOKIE_STATE_PROMPT:
  3200. nMsg = BINDSTATUS_COOKIE_STATE_PROMPT;
  3201. break;
  3202. case COOKIE_STATE_ACCEPT:
  3203. nMsg = BINDSTATUS_COOKIE_STATE_ACCEPT;
  3204. break;
  3205. case COOKIE_STATE_REJECT:
  3206. nMsg = BINDSTATUS_COOKIE_STATE_REJECT;
  3207. break;
  3208. case COOKIE_STATE_LEASH:
  3209. nMsg = BINDSTATUS_COOKIE_STATE_LEASH;
  3210. break;
  3211. case COOKIE_STATE_DOWNGRADE:
  3212. nMsg = BINDSTATUS_COOKIE_STATE_DOWNGRADE;
  3213. break;
  3214. default:
  3215. nMsg = BINDSTATUS_COOKIE_STATE_UNKNOWN;
  3216. break;
  3217. }
  3218. return nMsg;
  3219. }
  3220. HRESULT CINet::OnCookieNotification(DWORD dwStatus, IN LPVOID pvInfo)
  3221. {
  3222. DEBUG_ENTER((DBG_APP,
  3223. Hresult,
  3224. "CINet::OnCookieNotification",
  3225. "this=%#x, %#x, %#x",
  3226. this, dwStatus, pvInfo
  3227. ));
  3228. HRESULT hr = ERROR_SUCCESS;
  3229. BINDSTATUS nMsg;
  3230. DWORD dwBlock = 0;
  3231. switch (dwStatus)
  3232. {
  3233. case INTERNET_STATUS_P3P_HEADER:
  3234. {
  3235. TransAssert(pvInfo && "pvInfo should be a pointer to the P3P header");
  3236. hr = ReportNotification(BINDSTATUS_P3P_HEADER, (LPSTR)pvInfo);
  3237. break;
  3238. }
  3239. case INTERNET_STATUS_P3P_POLICYREF:
  3240. {
  3241. TransAssert(pvInfo && "pvInfo should be pointer to policy-ref URL");
  3242. if (char *pszPolicyRef = (char*) pvInfo)
  3243. hr = ReportNotification(BINDSTATUS_POLICY_HREF, (LPSTR)pszPolicyRef);
  3244. break;
  3245. }
  3246. case INTERNET_STATUS_COOKIE_HISTORY:
  3247. {
  3248. InternetCookieHistory *pPastActions = (InternetCookieHistory*) pvInfo;
  3249. if (!pPastActions)
  3250. break;
  3251. if (pPastActions->fAccepted)
  3252. ReportNotification(BINDSTATUS_COOKIE_STATE_ACCEPT, NULL);
  3253. if (pPastActions->fLeashed)
  3254. ReportNotification(BINDSTATUS_COOKIE_STATE_LEASH, NULL);
  3255. if (pPastActions->fDowngraded)
  3256. ReportNotification(BINDSTATUS_COOKIE_STATE_DOWNGRADE, NULL);
  3257. if (pPastActions->fRejected)
  3258. ReportNotification(BINDSTATUS_COOKIE_STATE_REJECT, NULL);
  3259. break;
  3260. }
  3261. case INTERNET_STATUS_COOKIE_SENT:
  3262. {
  3263. OutgoingCookieState* pOutgoing = (OutgoingCookieState *)pvInfo;
  3264. TransAssert(pOutgoing && "pvInfo should be OutgoingCookieState*");
  3265. if (pOutgoing->cSent)
  3266. {
  3267. hr = ReportNotification(BINDSTATUS_COOKIE_SENT, pOutgoing->pszLocation);
  3268. }
  3269. if (pOutgoing->cSuppressed)
  3270. {
  3271. hr = ReportNotification(BINDSTATUS_COOKIE_SUPPRESSED, pOutgoing->pszLocation);
  3272. }
  3273. break;
  3274. }
  3275. case INTERNET_STATUS_COOKIE_RECEIVED:
  3276. {
  3277. IncomingCookieState* pIncoming = (IncomingCookieState *)pvInfo;
  3278. TransAssert(pIncoming && "pvInfo should be OutgoingCookieState*");
  3279. if (pIncoming->cAccepted)
  3280. hr = ReportNotification(BINDSTATUS_COOKIE_STATE_ACCEPT, pIncoming->pszLocation);
  3281. if (SUCCEEDED(hr) && pIncoming->cLeashed)
  3282. hr = ReportNotification(BINDSTATUS_COOKIE_STATE_LEASH, pIncoming->pszLocation);
  3283. if (SUCCEEDED(hr) && pIncoming->cDowngraded)
  3284. hr = ReportNotification(BINDSTATUS_COOKIE_STATE_DOWNGRADE, pIncoming->pszLocation);
  3285. if (SUCCEEDED(hr) && pIncoming->cBlocked)
  3286. hr = ReportNotification(BINDSTATUS_COOKIE_STATE_REJECT, pIncoming->pszLocation);
  3287. break;
  3288. }
  3289. default:
  3290. TransAssert(FALSE);
  3291. break;
  3292. }
  3293. DEBUG_LEAVE(hr);
  3294. return hr;
  3295. }
  3296. #define HRESULT_FROM_WININET(pv) HRESULT_FROM_WIN32( (((LPINTERNET_ASYNC_RESULT) (pv) )->dwError) )
  3297. //+---------------------------------------------------------------------------
  3298. //
  3299. // Method: CINet::CINetCallback
  3300. //
  3301. // Synopsis:
  3302. //
  3303. // Arguments: [hInternet] --
  3304. // [dwContext] --
  3305. // [dwStatus] --
  3306. // [pvInfo] --
  3307. // [dwStatusLen] --
  3308. //
  3309. // Returns:
  3310. //
  3311. // History: 1-27-96 JohannP (Johann Posch) Created
  3312. //
  3313. // Notes:
  3314. //
  3315. //----------------------------------------------------------------------------
  3316. VOID CALLBACK CINet::CINetCallback(IN HINTERNET hInternet, IN DWORD_PTR dwContext,
  3317. IN DWORD dwStatus, IN LPVOID pvInfo, IN DWORD dwStatusLen)
  3318. {
  3319. DEBUG_ENTER((DBG_APP,
  3320. None,
  3321. "CINet::CINetCallback",
  3322. "%#x, %#x, %#x, %#x, %#x",
  3323. hInternet, dwContext, dwStatus, pvInfo, dwStatusLen
  3324. ));
  3325. // If this is a request, then we know the cookie type
  3326. CINet *pCINet = (CINet *) dwContext;
  3327. HRESULT hrError = INET_E_OK;
  3328. //
  3329. // handle callback without a context
  3330. if (!dwContext)
  3331. {
  3332. switch (dwStatus)
  3333. {
  3334. default:
  3335. //PProtAssert((FALSE));
  3336. break;
  3337. case INTERNET_STATUS_STATE_CHANGE :
  3338. {
  3339. DWORD dwState = *(DWORD *) pvInfo;
  3340. g_cInetState.SetState(dwState);
  3341. }
  3342. break;
  3343. } // end switch
  3344. }
  3345. else
  3346. {
  3347. PerfDbgLog2(tagCINet, pCINet, "+CINet::CINetCallback Status:%ld, State:%ld",
  3348. dwStatus, pCINet->_INState);
  3349. DWORD_PTR dwAsyncResult;
  3350. // from here the original thread needs to be told of various things
  3351. // such as errors, operation done etc.
  3352. PProtAssert((pCINet));
  3353. // guard this call - request might be aborted
  3354. //pCINet->AddRef();
  3355. DWORD dwFault;
  3356. #ifdef INET_CALLBACK_EXCEPTION
  3357. _try
  3358. #endif // INET_CALLBACK_EXCEPTION
  3359. {
  3360. switch (dwStatus)
  3361. {
  3362. // the net connection state changed
  3363. case INTERNET_STATUS_STATE_CHANGE :
  3364. {
  3365. DWORD dwState = *(DWORD *) pvInfo;
  3366. pCINet->OnINetStateChange(dwState);
  3367. }
  3368. break;
  3369. // callback to put up UI
  3370. case INTERNET_STATUS_USER_INPUT_REQUIRED:
  3371. {
  3372. // guard this call - request might be aborted
  3373. pCINet->PrivAddRef();
  3374. PProtAssert(pCINet->_INState == INetState_SEND_REQUEST);
  3375. //PProtAssert(!((LPINTERNET_ASYNC_RESULT)pvInfo)->dwResult);
  3376. LPVOID lpvSendRequestResultData = (LPVOID) ((LPINTERNET_ASYNC_RESULT)pvInfo)->dwResult;
  3377. DWORD dwSendRequestResult = ((LPINTERNET_ASYNC_RESULT) (pvInfo) )->dwError;
  3378. // handle the error here in particular pass on info for zone crossing
  3379. pCINet->OnINetSuspendSendRequest(dwSendRequestResult, lpvSendRequestResultData);
  3380. // unguard - release
  3381. pCINet->PrivRelease();
  3382. }
  3383. break;
  3384. // request completed
  3385. case INTERNET_STATUS_REQUEST_COMPLETE:
  3386. {
  3387. // guard this call - request might be aborted
  3388. pCINet->PrivAddRef();
  3389. if (pCINet->_INState != INetState_ERROR)
  3390. {
  3391. PProtAssert((pCINet->GetStatePending() == E_PENDING));
  3392. }
  3393. switch (pCINet->_INState)
  3394. {
  3395. case INetState_OPEN_REQUEST:
  3396. // the internet session handle is supposed to be returned
  3397. dwAsyncResult = ((LPINTERNET_ASYNC_RESULT)pvInfo)->dwResult;
  3398. if (dwAsyncResult)
  3399. {
  3400. // got the internet session handle back
  3401. pCINet->OnINetAsyncOpen(dwAsyncResult);
  3402. }
  3403. else
  3404. {
  3405. hrError = pCINet->SetBindResult(((LPINTERNET_ASYNC_RESULT) (pvInfo))->dwError, INET_E_NO_SESSION);
  3406. }
  3407. break;
  3408. case INetState_CONNECT_REQUEST:
  3409. // the server handle is supposed to be returned
  3410. dwAsyncResult = ((LPINTERNET_ASYNC_RESULT)pvInfo)->dwResult;
  3411. if (dwAsyncResult)
  3412. {
  3413. pCINet->OnINetConnect(dwAsyncResult);
  3414. }
  3415. else
  3416. {
  3417. hrError = pCINet->SetBindResult(((LPINTERNET_ASYNC_RESULT) (pvInfo))->dwError,INET_E_CANNOT_CONNECT);
  3418. }
  3419. break;
  3420. case INetState_PROTOPEN_REQUEST:
  3421. // the request handle is suppost to be returned
  3422. dwAsyncResult = ((LPINTERNET_ASYNC_RESULT)pvInfo)->dwResult;
  3423. if (dwAsyncResult)
  3424. {
  3425. pCINet->OnINetOpenRequest(dwAsyncResult);
  3426. }
  3427. else
  3428. {
  3429. hrError = pCINet->SetBindResult(((LPINTERNET_ASYNC_RESULT) (pvInfo))->dwError,INET_E_OBJECT_NOT_FOUND);
  3430. }
  3431. break;
  3432. case INetState_SEND_REQUEST:
  3433. {
  3434. // SendRequest returns a BOOL
  3435. dwAsyncResult = ((LPINTERNET_ASYNC_RESULT)pvInfo)->dwResult;
  3436. if (dwAsyncResult)
  3437. {
  3438. // pass on 0 and look up the status code with HttpQueryInfo
  3439. pCINet->OnINetSendRequest(0);
  3440. }
  3441. else
  3442. {
  3443. DWORD dwSendRequestResult = ((LPINTERNET_ASYNC_RESULT) (pvInfo) )->dwError;
  3444. // handle the error here in particular pass on info for zone crossing
  3445. if (dwSendRequestResult)
  3446. {
  3447. // handle the sendrequest result
  3448. // zone crossing
  3449. switch (dwSendRequestResult)
  3450. {
  3451. case ERROR_INTERNET_SEC_CERT_DATE_INVALID :
  3452. case ERROR_INTERNET_SEC_CERT_CN_INVALID :
  3453. case ERROR_INTERNET_HTTP_TO_HTTPS_ON_REDIR :
  3454. case ERROR_INTERNET_HTTPS_TO_HTTP_ON_REDIR :
  3455. case ERROR_INTERNET_HTTPS_HTTP_SUBMIT_REDIR :
  3456. case ERROR_HTTP_REDIRECT_NEEDS_CONFIRMATION :
  3457. case ERROR_INTERNET_INVALID_CA :
  3458. case ERROR_INTERNET_CLIENT_AUTH_CERT_NEEDED :
  3459. case ERROR_INTERNET_FORTEZZA_LOGIN_NEEDED :
  3460. case ERROR_INTERNET_FORCE_RETRY :
  3461. case ERROR_INTERNET_SEC_CERT_ERRORS :
  3462. case ERROR_INTERNET_SEC_CERT_REV_FAILED :
  3463. case ERROR_INTERNET_SEC_CERT_REVOKED :
  3464. case ERROR_INTERNET_LOGIN_FAILURE_DISPLAY_ENTITY_BODY:
  3465. pCINet->OnINetSendRequest(dwSendRequestResult);
  3466. break;
  3467. default:
  3468. hrError = pCINet->SetBindResult(((LPINTERNET_ASYNC_RESULT) (pvInfo))->dwError);
  3469. break;
  3470. }
  3471. }
  3472. else
  3473. {
  3474. hrError = pCINet->SetBindResult(((LPINTERNET_ASYNC_RESULT) (pvInfo))->dwError);
  3475. }
  3476. }
  3477. }
  3478. break;
  3479. case INetState_READ:
  3480. // InternetRead returns TRUE of FALSE
  3481. dwAsyncResult = ((LPINTERNET_ASYNC_RESULT)pvInfo)->dwResult;
  3482. if (dwAsyncResult)
  3483. {
  3484. pCINet->OnINetRead(dwAsyncResult);
  3485. }
  3486. else
  3487. {
  3488. hrError = pCINet->SetBindResult(((LPINTERNET_ASYNC_RESULT) (pvInfo))->dwError);
  3489. }
  3490. break;
  3491. case INetState_DATA_AVAILABLE:
  3492. {
  3493. DWORD_PTR dwResult = ((LPINTERNET_ASYNC_RESULT)(pvInfo))->dwResult;
  3494. if (dwResult)
  3495. {
  3496. DWORD dwBytes = ((LPINTERNET_ASYNC_RESULT) (pvInfo) )->dwError;
  3497. pCINet->OnINetDataAvailable(dwBytes);
  3498. }
  3499. else
  3500. {
  3501. hrError = pCINet->SetBindResult(((LPINTERNET_ASYNC_RESULT) (pvInfo))->dwError);
  3502. }
  3503. }
  3504. break;
  3505. case INetState_READ_DIRECT:
  3506. {
  3507. pCINet->OnINetReadDirect(0);
  3508. }
  3509. break;
  3510. case INetState_DATA_AVAILABLE_DIRECT:
  3511. {
  3512. PProtAssert((FALSE));
  3513. }
  3514. break;
  3515. default:
  3516. break;
  3517. }
  3518. // unguard - release
  3519. pCINet->PrivRelease();
  3520. }
  3521. break;
  3522. case INTERNET_STATUS_RESOLVING_NAME :
  3523. {
  3524. // get server name or proxy as string
  3525. //pCINet->ReportNotification(Notify_FindingServer, (LPSTR) pvInfo);
  3526. pCINet->ReportNotification(BINDSTATUS_FINDINGRESOURCE, (LPSTR) pvInfo);
  3527. }
  3528. break;
  3529. case INTERNET_STATUS_DETECTING_PROXY :
  3530. {
  3531. // indicate that auto-proxy detection is in progress
  3532. pCINet->ReportNotification(BINDSTATUS_PROXYDETECTING, (LPSTR) NULL);
  3533. }
  3534. break;
  3535. case INTERNET_STATUS_CONNECTING_TO_SERVER :
  3536. {
  3537. // get ip address as string
  3538. //pCINet->ReportNotification(Notify_Connecting, (LPSTR) pvInfo);
  3539. pCINet->ReportNotification(BINDSTATUS_CONNECTING, (LPSTR) pvInfo);
  3540. }
  3541. break;
  3542. case INTERNET_STATUS_SENDING_REQUEST :
  3543. {
  3544. // no data passed back
  3545. //pCINet->ReportNotification(Notify_SendingRequest);
  3546. pCINet->ReportNotification(BINDSTATUS_SENDINGREQUEST);
  3547. }
  3548. break;
  3549. case INTERNET_STATUS_REDIRECT :
  3550. {
  3551. PerfDbgLog1(tagCINet, pCINet, "+CINet::CINetCallback Redirected by WinINet (szRedirectUrl:%s)", (LPSTR) pvInfo);
  3552. // pvinfo contains the new url
  3553. pCINet->OnRedirect((LPSTR) pvInfo);
  3554. }
  3555. break;
  3556. case INTERNET_STATUS_HANDLE_CLOSING :
  3557. {
  3558. if ((*(LPHINTERNET)pvInfo) == pCINet->_hServer)
  3559. {
  3560. hrError = INET_E_OK;
  3561. PerfDbgLog1(tagCINet, pCINet, "=== CINet::CINetCallback (Close Service Handle:%lx)", (*(LPHINTERNET) pvInfo));
  3562. PProtAssert((pCINet->_HandleStateServer == HandleState_Closed));
  3563. // this is the connect handle - call Release
  3564. pCINet->_hServer = 0;
  3565. pCINet->PrivRelease(TRUE);
  3566. }
  3567. else if ((*(LPHINTERNET)pvInfo) == pCINet->_hRequest)
  3568. {
  3569. hrError = INET_E_OK;
  3570. PerfDbgLog1(tagCINet, pCINet, "=== CINet::CINetCallback (Close Request Handle:%lx)", (*(LPHINTERNET) pvInfo));
  3571. PProtAssert(( pCINet->_HandleStateRequest == HandleState_Closed));
  3572. // this is the connect handle - call Release
  3573. pCINet->_hRequest = 0;
  3574. pCINet->ReleaseTransAndBindInfo();
  3575. pCINet->PrivRelease(TRUE);
  3576. }
  3577. }
  3578. break;
  3579. case INTERNET_STATUS_COOKIE_SENT:
  3580. case INTERNET_STATUS_COOKIE_RECEIVED:
  3581. case INTERNET_STATUS_COOKIE_HISTORY:
  3582. case INTERNET_STATUS_PRIVACY_IMPACTED:
  3583. case INTERNET_STATUS_P3P_HEADER:
  3584. case INTERNET_STATUS_P3P_POLICYREF:
  3585. {
  3586. pCINet->OnCookieNotification(dwStatus, pvInfo);
  3587. }
  3588. break;
  3589. case INTERNET_STATUS_HANDLE_CREATED :
  3590. case INTERNET_STATUS_NAME_RESOLVED :
  3591. case INTERNET_STATUS_CONNECTED_TO_SERVER :
  3592. case INTERNET_STATUS_REQUEST_SENT :
  3593. case INTERNET_STATUS_RECEIVING_RESPONSE :
  3594. case INTERNET_STATUS_RESPONSE_RECEIVED :
  3595. case INTERNET_STATUS_CTL_RESPONSE_RECEIVED :
  3596. case INTERNET_STATUS_PREFETCH :
  3597. case INTERNET_STATUS_CLOSING_CONNECTION :
  3598. case INTERNET_STATUS_CONNECTION_CLOSED :
  3599. default:
  3600. {
  3601. //handle other status here
  3602. }
  3603. } // end switch
  3604. if (hrError != INET_E_OK)
  3605. {
  3606. PerfDbgLog2(tagCINet, pCINet, "=== CINet::CINetCallback _hrINet:%lx, ERROR: %lx",
  3607. pCINet->_hrINet, hrError);
  3608. // we need to terminate here
  3609. pCINet->ReportResultAndStop(pCINet->_hrINet);
  3610. }
  3611. // unguard - release
  3612. //pCINet->Release();
  3613. }
  3614. #ifdef INET_CALLBACK_EXCEPTION
  3615. _except(UrlMonInvokeExceptionFilter(GetExceptionCode(), GetExceptionInformation()))
  3616. {
  3617. dwFault = GetExceptionCode();
  3618. #if DBG == 1
  3619. //
  3620. // UrlMon catches exceptions when the client generates them. This is so we can
  3621. // cleanup properly, and allow urlmon to continue.
  3622. //
  3623. if ( dwFault == STATUS_ACCESS_VIOLATION
  3624. || dwFault == 0xC0000194 /*STATUS_POSSIBLE_DEADLOCK*/
  3625. || dwFault == 0xC00000AA /*STATUS_INSTRUCTION_MISALIGNMENT*/
  3626. || dwFault == 0x80000002 /*STATUS_DATATYPE_MISALIGNMENT*/ )
  3627. {
  3628. WCHAR iidName[256];
  3629. iidName[0] = 0;
  3630. char achProgname[256];
  3631. achProgname[0] = 0;
  3632. GetModuleFileNameA(NULL,achProgname,sizeof(achProgname));
  3633. DbgLog2(tagCINetErr, NULL,
  3634. "NotificationMgr has caught a fault 0x%08x on behalf of application %s",
  3635. dwFault, achProgname);
  3636. //TransAssert((!"The application has faulted processing. Check the kernel debugger for useful output.URLMon can continue but you probably want to stop and debug the application."));
  3637. }
  3638. #endif
  3639. }
  3640. #ifdef unix
  3641. __endexcept
  3642. #endif /* unix */
  3643. #endif INET_CALLBACK_EXCEPTION
  3644. }
  3645. PerfDbgLog1(tagCINet, pCINet, "-CINet::CINetCallback (hrError:%lx)", hrError);
  3646. DEBUG_LEAVE(0);
  3647. }
  3648. //+---------------------------------------------------------------------------
  3649. //
  3650. // Method: CINet::TransitState
  3651. //
  3652. // Synopsis:
  3653. //
  3654. // Arguments: [dwState] --
  3655. //
  3656. // Returns:
  3657. //
  3658. // History: 1-27-96 JohannP (Johann Posch) Created
  3659. //
  3660. // Notes:
  3661. //
  3662. //----------------------------------------------------------------------------
  3663. void CINet::TransitState(DWORD dwState, BOOL fAsync)
  3664. {
  3665. DEBUG_ENTER((DBG_APP,
  3666. None,
  3667. "CINet::TransitState",
  3668. "this=%#x, %#x, %B",
  3669. this, dwState, fAsync
  3670. ));
  3671. PerfDbgLog(tagCINet, this, "+CINet::TransitState");
  3672. if ((_dwState != INetState_DONE) && (_dwState != INetState_ERROR))
  3673. {
  3674. BINDSTATUS NMsg = (BINDSTATUS) ((fAsync) ? BINDSTATUS_INTERNALASYNC : BINDSTATUS_INTERNAL);
  3675. DWORD dwFlags = 0;
  3676. if ( NMsg == BINDSTATUS_INTERNALASYNC
  3677. || NMsg == BINDSTATUS_ERROR
  3678. || NMsg == BINDSTATUS_INTERNALASYNC)
  3679. {
  3680. dwFlags |= PI_FORCE_ASYNC;
  3681. }
  3682. if ( (dwState == INetState_AUTHENTICATE)
  3683. || (dwState == INetState_DISPLAY_UI)
  3684. || (_fForceSwitch))
  3685. {
  3686. dwFlags |= PD_FORCE_SWITCH;
  3687. }
  3688. if( _grfBindF & BINDF_FROMURLMON )
  3689. {
  3690. CStateInfo CSI = CStateInfo(NMsg, dwFlags, (LPVOID)(ULongToPtr((ULONG)dwState)));
  3691. if( _pCTrans )
  3692. {
  3693. _pCTrans->Switch(&CSI);
  3694. }
  3695. }
  3696. else
  3697. {
  3698. CStateInfo* pCSI = new CStateInfo(NMsg, dwFlags, (LPVOID)(ULongToPtr((ULONG)dwState)));
  3699. if( !pCSI )
  3700. {
  3701. ReportResultAndStop(E_OUTOFMEMORY);
  3702. }
  3703. else
  3704. {
  3705. if( dwFlags & PD_FORCE_SWITCH || _fForceSwitch )
  3706. {
  3707. if( _pCTrans )
  3708. {
  3709. _pCTrans->Switch(pCSI);
  3710. }
  3711. }
  3712. else
  3713. {
  3714. Continue(pCSI);
  3715. }
  3716. }
  3717. }
  3718. }
  3719. PerfDbgLog(tagCINet, this, "-CINet::TransitState");
  3720. DEBUG_LEAVE(0);
  3721. }
  3722. //+---------------------------------------------------------------------------
  3723. //
  3724. // Method: CINet::OnINetInternal
  3725. //
  3726. // Synopsis:
  3727. //
  3728. // Arguments: [dwState] --
  3729. //
  3730. // Returns:
  3731. //
  3732. // History: 1-27-96 JohannP (Johann Posch) Created
  3733. //
  3734. // Notes:
  3735. //
  3736. //----------------------------------------------------------------------------
  3737. void CINet::OnINetInternal(DWORD_PTR dwState)
  3738. {
  3739. DEBUG_ENTER((DBG_APP,
  3740. None,
  3741. "CINet::OnINetInternal",
  3742. "this=%#x, %#x",
  3743. this, dwState
  3744. ));
  3745. PerfDbgLog(tagCINet, this, "+CINet::OnINetInternal");
  3746. HRESULT hr = NOERROR;
  3747. if ((_dwState != INetState_DONE) && (_dwState != INetState_ERROR))
  3748. {
  3749. switch (dwState)
  3750. {
  3751. case INetState_START :
  3752. // is requested
  3753. hr = INetAsyncOpen();
  3754. break;
  3755. case INetState_OPEN_REQUEST :
  3756. hr = INetAsyncConnect();
  3757. break;
  3758. case INetState_CONNECT_REQUEST :
  3759. hr = INetAsyncOpenRequest();
  3760. break;
  3761. case INetState_PROTOPEN_REQUEST:
  3762. hr = INetAsyncSendRequest();
  3763. break;
  3764. case INetState_SEND_REQUEST :
  3765. if( _fSendRequestAgain )
  3766. {
  3767. _fCompleted = FALSE;
  3768. _fSendAgain = TRUE;
  3769. _fSendRequestAgain = FALSE;
  3770. hr = INetAsyncSendRequest();
  3771. }
  3772. else
  3773. {
  3774. hr = INetQueryInfo();
  3775. }
  3776. break;
  3777. case INetState_DISPLAY_UI :
  3778. hr = INetDisplayUI();
  3779. break;
  3780. case INetState_AUTHENTICATE :
  3781. hr = INetAuthenticate();
  3782. break;
  3783. case INetState_READ :
  3784. hr = INetRead();
  3785. break;
  3786. case INetState_READ_DIRECT :
  3787. hr = INetReadDirect();
  3788. break;
  3789. case INetState_DATA_AVAILABLE :
  3790. hr = INetReportAvailableData();
  3791. break;
  3792. case INetState_INETSTATE_CHANGE:
  3793. hr = INetStateChange();
  3794. break;
  3795. case INetState_DONE :
  3796. break;
  3797. default:
  3798. break;
  3799. }
  3800. }
  3801. /*
  3802. else
  3803. {
  3804. PProtAssert((FALSE && "Unknown state"));
  3805. }
  3806. */
  3807. if ((hr != NOERROR) && (hr != E_PENDING))
  3808. {
  3809. ReportResultAndStop(hr);
  3810. }
  3811. PerfDbgLog(tagCINet, this, "-CINet::OnINetInternal");
  3812. DEBUG_LEAVE(0);
  3813. }
  3814. //+---------------------------------------------------------------------------
  3815. //
  3816. // Method: CINet::TerminateRequest
  3817. //
  3818. // Synopsis: Close the server and request handle - wininet will make a
  3819. // callback on each handle closed
  3820. //
  3821. // Arguments: (none)
  3822. //
  3823. // Returns:
  3824. //
  3825. // History: 1-27-96 JohannP (Johann Posch) Created
  3826. //
  3827. // Notes:
  3828. //
  3829. //----------------------------------------------------------------------------
  3830. void CINet::TerminateRequest()
  3831. {
  3832. DEBUG_ENTER((DBG_APP,
  3833. None,
  3834. "CINet::TerminateRequest",
  3835. "this=%#x",
  3836. this
  3837. ));
  3838. PerfDbgLog(tagCINet, this, "+CINet::TerminateRequest");
  3839. CLock lck(_mxs); // only one thread should be in here
  3840. if ((_HandleStateRequest == HandleState_Initialized))
  3841. {
  3842. PProtAssert((_hRequest));
  3843. _HandleStateRequest = HandleState_Closed;
  3844. InternetCloseHandle(_hRequest);
  3845. //_hRequest = 0;
  3846. }
  3847. else if ((_HandleStateRequest == HandleState_Pending))
  3848. {
  3849. _HandleStateRequest = HandleState_Aborted;
  3850. }
  3851. if (_HandleStateServer == HandleState_Initialized)
  3852. {
  3853. PerfDbgLog1(tagCINet, this, "=== CINet::TerminateRequest InternetCloseHandle (hServer:%lx)", _hServer);
  3854. _HandleStateServer = HandleState_Closed;
  3855. if (_hServer)
  3856. {
  3857. // the handle can be NULL
  3858. // in case we got aborted during the
  3859. // pending open request
  3860. InternetCloseHandle(_hServer);
  3861. }
  3862. }
  3863. else if ((_HandleStateServer == HandleState_Pending))
  3864. {
  3865. _HandleStateServer = HandleState_Aborted;
  3866. }
  3867. PerfDbgLog(tagCINet, this, "-CINet::TerminateRequest");
  3868. DEBUG_LEAVE(0);
  3869. }
  3870. //+---------------------------------------------------------------------------
  3871. //
  3872. // Method: CINet::FindTagInHeader
  3873. //
  3874. // Synopsis:
  3875. //
  3876. // Arguments: [lpszBuffer] --
  3877. // [lpszTag] --
  3878. //
  3879. // Returns:
  3880. //
  3881. // History: 1-27-96 JohannP (Johann Posch) Created
  3882. //
  3883. // Notes:
  3884. //
  3885. //----------------------------------------------------------------------------
  3886. LPSTR CINet::FindTagInHeader(LPCSTR lpszBuffer, LPCSTR lpszTag)
  3887. {
  3888. DEBUG_ENTER((DBG_APP,
  3889. String,
  3890. "CINet::FindTagInHeader",
  3891. "this=%#x, %.80q, %.80q",
  3892. this, lpszBuffer, lpszTag
  3893. ));
  3894. PerfDbgLog(tagCINet, this, "+CINet::FindTagInHeader");
  3895. LPCSTR p;
  3896. int i, cbTagLen;
  3897. cbTagLen = strlen(lpszTag);
  3898. for (p = lpszBuffer; i = strlen(p); p += (i + 1))
  3899. {
  3900. if (!StrCmpNI(p, lpszTag, cbTagLen))
  3901. {
  3902. DEBUG_LEAVE((LPSTR)p);
  3903. return (LPSTR)p;
  3904. }
  3905. }
  3906. PerfDbgLog(tagCINet, this, "-CINet::FindTagInHeader");
  3907. DEBUG_LEAVE(NULL);
  3908. return NULL;
  3909. }
  3910. //+---------------------------------------------------------------------------
  3911. //
  3912. // Method: CINet::INetDataAvailable
  3913. //
  3914. // Synopsis:
  3915. //
  3916. // Arguments: (none)
  3917. //
  3918. // Returns:
  3919. //
  3920. // History: 2-23-96 JohannP (Johann Posch) Created
  3921. //
  3922. // Notes:
  3923. //
  3924. //----------------------------------------------------------------------------
  3925. HRESULT CINet::INetDataAvailable()
  3926. {
  3927. DEBUG_ENTER((DBG_APP,
  3928. Hresult,
  3929. "CINet::INetDataAvailable",
  3930. "this=%#x",
  3931. this
  3932. ));
  3933. PerfDbgLog(tagCINet, this, "+CINet::INetDataAvailable");
  3934. HRESULT hr = NOERROR;
  3935. BOOL fRet = FALSE;
  3936. PProtAssert((GetStatePending() == NOERROR));
  3937. SetINetState(INetState_DATA_AVAILABLE);
  3938. if (!_fFilenameReported)
  3939. {
  3940. char szFilename[MAX_PATH];
  3941. HRESULT hr1 = GetUrlCacheFilename(szFilename, MAX_PATH);
  3942. if (hr1 == NOERROR && szFilename[0] != '\0' )
  3943. {
  3944. ReportNotification(BINDSTATUS_CACHEFILENAMEAVAILABLE, (LPSTR) szFilename);
  3945. _fFilenameReported = TRUE;
  3946. }
  3947. }
  3948. // check if all data were read of the current buffer
  3949. SetStatePending(E_PENDING);
  3950. fRet = InternetQueryDataAvailable(_hRequest, &_cbReadReturn, 0, 0);
  3951. if (fRet == FALSE)
  3952. {
  3953. dwLstError = GetLastError();
  3954. if (dwLstError == ERROR_IO_PENDING)
  3955. {
  3956. hr = E_PENDING;
  3957. }
  3958. else
  3959. {
  3960. SetStatePending(NOERROR);
  3961. hr = _hrError = INET_E_DATA_NOT_AVAILABLE;
  3962. }
  3963. }
  3964. else
  3965. {
  3966. SetByteCountReadyToRead(_cbReadReturn);
  3967. SetStatePending(NOERROR);
  3968. if (_cbReadReturn == 0)
  3969. {
  3970. // done
  3971. _fDone = 1;
  3972. }
  3973. hr = INetReportAvailableData();
  3974. }
  3975. PerfDbgLog1(tagCINet, this, "-CINet::INetDataAvailable (hr:%lx)", hr);
  3976. DEBUG_LEAVE(hr);
  3977. return hr;
  3978. }
  3979. //+---------------------------------------------------------------------------
  3980. //
  3981. // Method: CINet::OnINetDataAvailable
  3982. //
  3983. // Synopsis:
  3984. //
  3985. // Arguments: [dwResult] --
  3986. //
  3987. // Returns:
  3988. //
  3989. // History: 2-23-96 JohannP (Johann Posch) Created
  3990. //
  3991. // Notes:
  3992. //
  3993. //----------------------------------------------------------------------------
  3994. HRESULT CINet::OnINetDataAvailable( DWORD dwResult)
  3995. {
  3996. DEBUG_ENTER((DBG_APP,
  3997. Hresult,
  3998. "CINet::OnINetDataAvailable",
  3999. "this=%#x, %#x",
  4000. this, dwResult
  4001. ));
  4002. PerfDbgLog1(tagCINet, this, "+CINet::OnINetDataAvailable (dwAvailable:%ld)", dwResult);
  4003. HRESULT hr = NOERROR;
  4004. PProtAssert((GetStatePending() == E_PENDING));
  4005. SetByteCountReadyToRead(dwResult);
  4006. if (dwResult == 0)
  4007. {
  4008. // done
  4009. _fDone = 1;
  4010. }
  4011. // set state to normal - no pending transaction
  4012. SetStatePending(NOERROR);
  4013. // notification for next request
  4014. TransitState(INetState_DATA_AVAILABLE);
  4015. PerfDbgLog1(tagCINet, this, "-CINet::OnINetDataAvailable (hr:%lx)", hr);
  4016. DEBUG_LEAVE(hr);
  4017. return hr;
  4018. }
  4019. //+---------------------------------------------------------------------------
  4020. //
  4021. // Method: CINet::INetReportAvailableData
  4022. //
  4023. // Synopsis:
  4024. //
  4025. // Arguments: (none)
  4026. //
  4027. // Returns:
  4028. //
  4029. // History: 2-23-96 JohannP (Johann Posch) Created
  4030. //
  4031. // Notes:
  4032. //
  4033. //----------------------------------------------------------------------------
  4034. HRESULT CINet::INetReportAvailableData()
  4035. {
  4036. DEBUG_ENTER((DBG_APP,
  4037. Hresult,
  4038. "CINet::INetReportAvailableData",
  4039. "this=%#x",
  4040. this
  4041. ));
  4042. PerfDbgLog(tagCINet, this, "+CINet::INetReportAvailableData");
  4043. HRESULT hr = NOERROR;
  4044. DWORD dwError;
  4045. ULONG cbBytesAvailable = 0;
  4046. //BUGBUG: we hit this assertion sometimes.
  4047. //PProtAssert((GetStatePending() == NOERROR));
  4048. _hrError = INET_E_OK;
  4049. if ((GetStatePending() == E_PENDING))
  4050. {
  4051. // nothing to do - data for this notfication
  4052. // already received
  4053. }
  4054. else if ((cbBytesAvailable = GetByteCountReadyToRead()) != 0)
  4055. {
  4056. if ( _fDone
  4057. || ( _cbTotalBytesRead
  4058. && _cbDataSize
  4059. && (_cbTotalBytesRead == _cbDataSize)))
  4060. {
  4061. _hrError = INET_E_DONE;
  4062. }
  4063. else
  4064. {
  4065. if(_cbDataSize && (_cbDataSize < (cbBytesAvailable + _cbTotalBytesRead)))
  4066. {
  4067. _cbDataSize = cbBytesAvailable + _cbTotalBytesRead;
  4068. }
  4069. if (_bscf & BSCF_DATAFULLYAVAILABLE)
  4070. {
  4071. _bscf |= BSCF_LASTDATANOTIFICATION;
  4072. _bscf &= ~BSCF_FIRSTDATANOTIFICATION;
  4073. }
  4074. // BUG-WORK pCTrans migh be gone by now
  4075. _cbSizeLastReportData = cbBytesAvailable + _cbTotalBytesRead;
  4076. hr = _pEmbdFilter->ReportData(_bscf, cbBytesAvailable + _cbTotalBytesRead, _cbDataSize);
  4077. if (_bscf & BSCF_FIRSTDATANOTIFICATION)
  4078. {
  4079. _bscf &= ~BSCF_FIRSTDATANOTIFICATION;
  4080. _bscf |= BSCF_INTERMEDIATEDATANOTIFICATION;
  4081. }
  4082. }
  4083. }
  4084. else if ( _fDone
  4085. || ( _cbTotalBytesRead
  4086. && _cbDataSize
  4087. && (_cbTotalBytesRead == _cbDataSize)))
  4088. {
  4089. if (_cbDataSize == 0)
  4090. {
  4091. _cbDataSize = _cbTotalBytesRead;
  4092. }
  4093. PerfDbgLog2(tagCINet, this, "=== CINet::INetReportAvailableData DONE! (cbTotalBytesRead:%ld, cbDataSize:%ld)", _cbTotalBytesRead, _cbDataSize);
  4094. // now we should have all data
  4095. PProtAssert(( ( ( _cbDataSize == 0)
  4096. || ((_cbDataSize != 0) && (_cbTotalBytesRead == _cbDataSize)))
  4097. && "Did not get all data!!"));
  4098. _hrError = INET_E_DONE;
  4099. }
  4100. if (_hrError != INET_E_OK)
  4101. {
  4102. _bscf |= BSCF_LASTDATANOTIFICATION;
  4103. if (_pCTrans )
  4104. {
  4105. _cbSizeLastReportData = _cbTotalBytesRead;
  4106. hr = _pEmbdFilter->ReportData(_bscf, _cbTotalBytesRead, _cbDataSize);
  4107. }
  4108. hr = NOERROR;
  4109. }
  4110. PerfDbgLog2(tagCINet, this, "-CINet::INetReportAvailableData (_hrError:%lx, hr:%lx)", _hrError, hr);
  4111. DEBUG_LEAVE(hr);
  4112. return hr;
  4113. }
  4114. //+---------------------------------------------------------------------------
  4115. //
  4116. // Method: CINet::ReadDataHere
  4117. //
  4118. // Synopsis:
  4119. //
  4120. // Arguments: [pBuffer] --
  4121. // [cbBytes] --
  4122. // [pcbBytes] --
  4123. //
  4124. // Returns:
  4125. //
  4126. // History: 2-13-96 JohannP (Johann Posch) Created
  4127. //
  4128. // Notes:
  4129. //
  4130. //----------------------------------------------------------------------------
  4131. HRESULT CINet::ReadDataHere(BYTE *pBuffer, DWORD cbBytes, DWORD *pcbBytes)
  4132. {
  4133. DEBUG_ENTER((DBG_APP,
  4134. Hresult,
  4135. "CINet::ReadDataHere",
  4136. "this=%#x, pBuffer, cbBytes, pcbBytes",
  4137. this, pBuffer, cbBytes, pcbBytes
  4138. ));
  4139. PerfDbgLog(tagCINet, this, "+CINet::ReadDataHere");
  4140. HRESULT hr = NOERROR;
  4141. DWORD dwError;
  4142. *pcbBytes = 0;
  4143. ULONG cbReadReturn = 0;
  4144. ULONG dwReturned = 0;
  4145. ULONG dwReturnedTotal = 0;
  4146. ULONG dwBytesLeft = cbBytes;
  4147. //BUGBUG: turn this assertion on again
  4148. //PProtAssert((GetStatePending() == NOERROR));
  4149. if (_hrError == INET_E_DONE)
  4150. {
  4151. // means end of file
  4152. hr = S_FALSE;
  4153. }
  4154. else if (GetStatePending() != NOERROR)
  4155. {
  4156. hr = E_PENDING;
  4157. }
  4158. else
  4159. {
  4160. _hrError = INET_E_OK;
  4161. do
  4162. {
  4163. if ((cbReadReturn = GetByteCountReadyToRead()) == 0)
  4164. {
  4165. BOOL fRet;
  4166. PerfDbgLog(tagCINet, this, "CINet::ReadDataHere -> InternetQueryDataAvailable");
  4167. PProtAssert((GetStatePending() == NOERROR));
  4168. SetStatePending(E_PENDING);
  4169. fRet = InternetQueryDataAvailable(_hRequest, &_cbReadReturn,0 ,0);
  4170. if (fRet == FALSE)
  4171. {
  4172. dwLstError = GetLastError();
  4173. if (dwLstError == ERROR_IO_PENDING)
  4174. {
  4175. hr = E_PENDING;
  4176. }
  4177. else
  4178. {
  4179. SetStatePending(NOERROR);
  4180. hr = _hrError = INET_E_DATA_NOT_AVAILABLE;
  4181. }
  4182. }
  4183. else
  4184. {
  4185. SetByteCountReadyToRead(_cbReadReturn);
  4186. SetStatePending(NOERROR);
  4187. if (_cbReadReturn == 0)
  4188. {
  4189. // download completed - no more data available
  4190. hr = _hrError = INET_E_DONE;
  4191. }
  4192. }
  4193. PerfDbgLog2(tagCINet, this, "CINet::ReadDataHere == InternetQueryDataAvailable (fRet:%d, _cbReadReturn:%ld)", fRet, _cbReadReturn);
  4194. }
  4195. // in case of noerror read the bits
  4196. if ((hr == NOERROR) && (_hrError == INET_E_OK))
  4197. {
  4198. cbReadReturn = GetByteCountReadyToRead();
  4199. PProtAssert((GetStatePending() == NOERROR));
  4200. // get the read buffer from the trans data object
  4201. PProtAssert(((pBuffer != NULL) && (cbBytes > 0)));
  4202. PProtAssert((cbReadReturn > 0));
  4203. dwBytesLeft = cbBytes - dwReturnedTotal;
  4204. if (dwBytesLeft > cbReadReturn)
  4205. {
  4206. dwBytesLeft = cbReadReturn;
  4207. }
  4208. PProtAssert(( dwBytesLeft <= (cbBytes - dwReturnedTotal) ));
  4209. dwReturned = 0;
  4210. PerfDbgLog1(tagCINet, this, "CINet::ReadDataHere -> InternetReadFile (dwBytesLeft:%ld)", dwBytesLeft);
  4211. if (!InternetReadFile(_hRequest, pBuffer + dwReturnedTotal, dwBytesLeft, &dwReturned))
  4212. {
  4213. dwError = GetLastError();
  4214. if (dwError != ERROR_IO_PENDING)
  4215. {
  4216. hr = _hrError = INET_E_DOWNLOAD_FAILURE;
  4217. DbgLog3(tagCINetErr, this, "CINet::ReadDataHere failed: (dwError:%lx, hr:%lx, hrError:%lx)",
  4218. dwError, hr, _hrError);
  4219. }
  4220. else
  4221. {
  4222. // Note: BIG ERROR - we need to shut down now
  4223. // wininet is using the client buffer and the client is not
  4224. // aware that the buffer is used during the pending time
  4225. //
  4226. DbgLog(tagCINetErr, this, "CINet::ReadDataHere - InternetReadFile returned E_PENDING!!!");
  4227. PProtAssert((FALSE && "CINet::ReadDataHere - InternetReadFile returned E_PENDING!!!"));
  4228. hr = _hrError = INET_E_DOWNLOAD_FAILURE;
  4229. }
  4230. PerfDbgLog1(tagCINet, this, "CINet::ReadDataHere == InternetReadFile (dwError:%lx)", dwError);
  4231. }
  4232. else
  4233. {
  4234. PerfDbgLog3(tagCINet, this, "CINet::ReadDataHere == InternetReadFile ==> (cbBytes:%ld, dwReturned:%ld,_cbReadReturn:%ld)",
  4235. cbBytes, dwReturned,_cbReadReturn);
  4236. PProtAssert(( (cbBytes + dwReturnedTotal) >= dwReturned ));
  4237. if (dwReturned == 0)
  4238. {
  4239. hr = _hrError = INET_E_DONE;
  4240. }
  4241. else
  4242. {
  4243. hr = NOERROR;
  4244. }
  4245. dwReturnedTotal += dwReturned;
  4246. cbReadReturn -= dwReturned;
  4247. SetByteCountReadyToRead(-(LONG)dwReturned);
  4248. _cbTotalBytesRead += dwReturned;
  4249. }
  4250. } // read case - bits available
  4251. PerfDbgLog4(tagCINet, this, "CINet::ReadDataHere ooo InternetReadFile ==>(cbBytes:%ld, dwReturned:%ld,cbReadReturn:%ld,dwReturnedTotal:%ld)",
  4252. cbBytes, dwReturned,cbReadReturn,dwReturnedTotal);
  4253. } while ((hr == NOERROR) && (dwReturnedTotal < cbBytes));
  4254. PProtAssert((dwReturnedTotal <= cbBytes));
  4255. *pcbBytes = dwReturnedTotal;
  4256. if (hr == INET_E_DONE)
  4257. {
  4258. hr = (dwReturnedTotal) ? S_OK : S_FALSE;
  4259. }
  4260. }
  4261. // Note: stop the download in case of DONE or ERROR!
  4262. if (_hrError != INET_E_OK)
  4263. {
  4264. ReportResultAndStop((hr == S_FALSE) ? NOERROR : hr, _cbTotalBytesRead, _cbDataSize);
  4265. }
  4266. PerfDbgLog4(tagCINet, this, "-CINet::ReadDataHere (_hrError:%lx, [hr:%lx,cbBytesAsked:%ld,cbBytesReturned:%ld])",
  4267. _hrError, hr, cbBytes, *pcbBytes);
  4268. DEBUG_LEAVE(hr);
  4269. return hr;
  4270. }
  4271. //+---------------------------------------------------------------------------
  4272. //
  4273. // Method: CINet::OperationOnAparmentThread
  4274. //
  4275. // Synopsis:
  4276. //
  4277. // Arguments: [dwState] --
  4278. //
  4279. // Returns:
  4280. //
  4281. // History: 1-27-96 JohannP (Johann Posch) Created
  4282. //
  4283. // Notes:
  4284. //
  4285. //----------------------------------------------------------------------------
  4286. BOOL CINet::OperationOnAparmentThread(DWORD dwState)
  4287. {
  4288. DEBUG_ENTER((DBG_APP,
  4289. Bool,
  4290. "CINet::OperationOnAparmentThread",
  4291. "this=%#x, %#x",
  4292. this, dwState
  4293. ));
  4294. PerfDbgLog(tagCINet, this, "+CINet::OperationOnAparmentThread");
  4295. BOOL fRet = FALSE;
  4296. switch (dwState)
  4297. {
  4298. case INetState_OPEN_REQUEST:
  4299. break;
  4300. case INetState_CONNECT_REQUEST:
  4301. break;
  4302. case INetState_PROTOPEN_REQUEST:
  4303. break;
  4304. case INetState_SEND_REQUEST:
  4305. break;
  4306. case INetState_READ:
  4307. case INetState_READ_DIRECT:
  4308. fRet = TRUE;
  4309. break;
  4310. default:
  4311. fRet = TRUE;
  4312. break;
  4313. }
  4314. //return fRet;
  4315. PerfDbgLog(tagCINet, this, "-CINet::OperationOnAparmentThread");
  4316. DEBUG_LEAVE(TRUE);
  4317. return TRUE;
  4318. }
  4319. //+---------------------------------------------------------------------------
  4320. //
  4321. // Method: CINet::OperationOnAparmentThread
  4322. //
  4323. // Synopsis:
  4324. //
  4325. // Returns:
  4326. //
  4327. // History: 10-27-98 DanpoZ (Danpo Zhang) Created
  4328. //
  4329. // Notes:
  4330. //
  4331. //----------------------------------------------------------------------------
  4332. BOOL CINet::UTF8Enabled()
  4333. {
  4334. DEBUG_ENTER((DBG_APP,
  4335. Bool,
  4336. "CINet::UTF8Enabled",
  4337. "this=%#x",
  4338. this
  4339. ));
  4340. BOOL bRet = FALSE;
  4341. // do not enable utf8 on file or ftp protocol
  4342. if( _dwIsA == DLD_PROTOCOL_FILE ||
  4343. _dwIsA == DLD_PROTOCOL_FTP )
  4344. {
  4345. goto exit;
  4346. }
  4347. // default to per-machine utf-8 setting
  4348. bRet = g_bGlobalUTF8Enabled;
  4349. // per-binding flag
  4350. if( _BndInfo.dwOptions & BINDINFO_OPTIONS_ENABLE_UTF8)
  4351. {
  4352. bRet = TRUE;
  4353. }
  4354. if( _BndInfo.dwOptions & BINDINFO_OPTIONS_DISABLE_UTF8)
  4355. {
  4356. bRet = FALSE;
  4357. }
  4358. if( _BndInfo.dwOptions & BINDINFO_OPTIONS_USE_IE_ENCODING)
  4359. {
  4360. DWORD dwIE;
  4361. DWORD dwOutLen = sizeof(DWORD);
  4362. HRESULT hr = UrlMkGetSessionOption(
  4363. URLMON_OPTION_URL_ENCODING,
  4364. &dwIE,
  4365. sizeof(DWORD),
  4366. &dwOutLen,
  4367. NULL );
  4368. if( hr == NOERROR )
  4369. {
  4370. if( dwIE == URL_ENCODING_ENABLE_UTF8 )
  4371. {
  4372. bRet = TRUE;
  4373. }
  4374. else if( dwIE == URL_ENCODING_DISABLE_UTF8 )
  4375. {
  4376. bRet = FALSE;
  4377. }
  4378. }
  4379. }
  4380. exit:
  4381. DEBUG_LEAVE(bRet);
  4382. return bRet;
  4383. }
  4384. //+---------------------------------------------------------------------------
  4385. //
  4386. // Method: CINet::QueryInfoOnResponse
  4387. //
  4388. // Synopsis:
  4389. //
  4390. // Arguments: (none)
  4391. //
  4392. // Returns:
  4393. //
  4394. // History: 1-27-96 JohannP (Johann Posch) Created
  4395. //
  4396. // Notes:
  4397. //
  4398. //----------------------------------------------------------------------------
  4399. HRESULT CINet::QueryInfoOnResponse()
  4400. {
  4401. DEBUG_ENTER((DBG_APP,
  4402. Hresult,
  4403. "CINet::QueryInfoOnResponse",
  4404. "this=%#x",
  4405. this
  4406. ));
  4407. PerfDbgLog(tagCINet, this, "+CINet::QueryInfoOnResponse");
  4408. HRESULT hr = NOERROR;
  4409. DWORD dwFlags;
  4410. DWORD cbLen = sizeof(dwFlags);
  4411. // See if it is from the cache
  4412. if (InternetQueryOption(_hRequest, INTERNET_OPTION_REQUEST_FLAGS, &dwFlags, &cbLen))
  4413. {
  4414. if (dwFlags & INTERNET_REQFLAG_FROM_CACHE)
  4415. {
  4416. _dwCacheFlags |= INTERNET_REQFLAG_FROM_CACHE;
  4417. // set flag that data are from cache
  4418. _bscf |= BSCF_DATAFULLYAVAILABLE;
  4419. }
  4420. }
  4421. hr = QueryStatusOnResponse();
  4422. if (hr == NOERROR)
  4423. {
  4424. hr = QueryHeaderOnResponse();
  4425. }
  4426. if (_hrError != INET_E_OK)
  4427. {
  4428. SetINetState(INetState_DONE);
  4429. }
  4430. PerfDbgLog1(tagCINet, this, "-CINet::QueryInfoOnResponse (hr:%lx)", hr);
  4431. DEBUG_LEAVE(hr);
  4432. return hr;
  4433. }
  4434. //+---------------------------------------------------------------------------
  4435. //
  4436. // Method: CINet::QueryStatusOnResponse
  4437. //
  4438. // Synopsis:
  4439. //
  4440. // Arguments: (none)
  4441. //
  4442. // Returns:
  4443. //
  4444. // History: 1-27-96 JohannP (Johann Posch) Created
  4445. //
  4446. // Notes:
  4447. //
  4448. //----------------------------------------------------------------------------
  4449. HRESULT CINet::QueryStatusOnResponse()
  4450. {
  4451. DEBUG_ENTER((DBG_APP,
  4452. Hresult,
  4453. "CINet::QueryStatusOnResponse",
  4454. "this=%#x",
  4455. this
  4456. ));
  4457. PerfDbgLog(tagCINet, this, "+CINet::QueryStatusOnResponse");
  4458. PProtAssert((FALSE));
  4459. PerfDbgLog1(tagCINet, this, "-CINet::QueryStatusOnResponse hr:%lx", E_FAIL);
  4460. DEBUG_LEAVE(E_FAIL);
  4461. return E_FAIL;
  4462. }
  4463. //+---------------------------------------------------------------------------
  4464. //
  4465. // Method: CINet::QueryStatusOnResponseDefault
  4466. //
  4467. // Synopsis:
  4468. //
  4469. // Arguments: (none)
  4470. //
  4471. // Returns:
  4472. //
  4473. // History: 1-27-96 JohannP (Johann Posch) Created
  4474. //
  4475. // Notes:
  4476. //
  4477. //----------------------------------------------------------------------------
  4478. HRESULT CINet::QueryStatusOnResponseDefault(DWORD dwStat)
  4479. {
  4480. DEBUG_ENTER((DBG_APP,
  4481. Hresult,
  4482. "CINet::QueryStatusOnResponseDefault",
  4483. "this=%#x, %#x",
  4484. this, dwStat
  4485. ));
  4486. PerfDbgLog(tagCINet, this, "+CINet::QueryStatusOnResponseDefault");
  4487. PProtAssert((FALSE));
  4488. PerfDbgLog1(tagCINet, this, "-CINet::QueryStatusOnResponseDefault hr:%lx", E_FAIL);
  4489. DEBUG_LEAVE(E_FAIL);
  4490. return E_FAIL;
  4491. }
  4492. //+---------------------------------------------------------------------------
  4493. //
  4494. // Method: CINet::QueryHeaderOnResponse
  4495. //
  4496. // Synopsis:
  4497. //
  4498. // Arguments: (none)
  4499. //
  4500. // Returns:
  4501. //
  4502. // History: 1-27-96 JohannP (Johann Posch) Created
  4503. //
  4504. // Notes:
  4505. //
  4506. //----------------------------------------------------------------------------
  4507. HRESULT CINet::QueryHeaderOnResponse()
  4508. {
  4509. DEBUG_ENTER((DBG_APP,
  4510. Hresult,
  4511. "CINet::QueryHeaderOnResponse",
  4512. "this=%#x",
  4513. this
  4514. ));
  4515. PerfDbgLog(tagCINet, this, "+CINet::QueryHeaderOnResponse");
  4516. PProtAssert((FALSE));
  4517. PerfDbgLog1(tagCINet, this, "-CINet::QueryHeaderOnResponse hr:%lx", E_FAIL);
  4518. DEBUG_LEAVE(E_FAIL);
  4519. return E_FAIL;
  4520. }
  4521. //+---------------------------------------------------------------------------
  4522. //
  4523. // Method: CINet::RedirectRequest
  4524. //
  4525. // Synopsis:
  4526. //
  4527. // Arguments: [lpszBuffer] --
  4528. // [pdwBuffSize] --
  4529. //
  4530. // Returns:
  4531. //
  4532. // History: 1-27-96 JohannP (Johann Posch) Created
  4533. //
  4534. // Notes:
  4535. //
  4536. //----------------------------------------------------------------------------
  4537. HRESULT CINet::RedirectRequest(LPSTR lpszBuffer, DWORD *pdwBuffSize, DWORD dwStatus)
  4538. {
  4539. DEBUG_ENTER((DBG_APP,
  4540. Hresult,
  4541. "CINet::RedirectRequest",
  4542. "this=%#x, %#x, %#x, %d",
  4543. this, lpszBuffer, pdwBuffSize, dwStatus
  4544. ));
  4545. PerfDbgLog(tagCINet, this, "+CINet::RedirectRequest");
  4546. PProtAssert((FALSE));
  4547. PerfDbgLog1(tagCINet, this, "-CINet::RedirectRequest(fRet:%ld)", FALSE);
  4548. DEBUG_LEAVE(E_FAIL);
  4549. return E_FAIL;
  4550. }
  4551. //+---------------------------------------------------------------------------
  4552. //
  4553. // Method: CINet::AuthenticationRequest
  4554. //
  4555. // Synopsis:
  4556. //
  4557. // Arguments: [lpszBuffer] --
  4558. // [pdwBuffSize] --
  4559. //
  4560. // Returns:
  4561. //
  4562. // History: 2-06-96 JohannP (Johann Posch) Created
  4563. //
  4564. // Notes:
  4565. //
  4566. //----------------------------------------------------------------------------
  4567. HRESULT CINet::AuthenticationRequest()
  4568. {
  4569. DEBUG_ENTER((DBG_APP,
  4570. Hresult,
  4571. "CINet::AuthenticationRequest",
  4572. "this=%#x",
  4573. this
  4574. ));
  4575. PerfDbgLog(tagCINet, this, "+CINet::AuthenticationRequest");
  4576. HRESULT hr = NOERROR;
  4577. DWORD dwError;
  4578. LPWSTR pwzUsername = NULL;
  4579. LPWSTR pwzPassword = NULL;
  4580. DWORD dwBindF = GetBindFlags();
  4581. PerfDbgLog2(tagCINet, this, "<1> _cbProxyAuthenticate:%d _cbAuthenticate:%d",
  4582. _cbProxyAuthenticate, _cbAuthenticate);
  4583. if (_fProxyAuth ? (_cbProxyAuthenticate >= AUTHENTICATE_MAX):(_cbAuthenticate >= AUTHENTICATE_MAX))
  4584. {
  4585. // NOTE: set the error to noerror and
  4586. // continue reading data and show the 401 contained
  4587. _hrINet = hr = NOERROR;
  4588. }
  4589. else
  4590. {
  4591. if (_hwndAuth == NULL)
  4592. {
  4593. IAuthenticate *pPInfo;
  4594. DbgLog(tagCINetErr, this, "+CINet::AuthenticationRequest: QS for IAuthenticate");
  4595. hr = QueryService(IID_IAuthenticate, (void **)&pPInfo);
  4596. if (hr == NOERROR)
  4597. {
  4598. PProtAssert((pPInfo));
  4599. hr = pPInfo->Authenticate(&_hwndAuth, &pwzUsername, &pwzPassword);
  4600. pPInfo->Release();
  4601. }
  4602. }
  4603. if (hr == NOERROR)
  4604. {
  4605. _hrINet = hr = E_ACCESSDENIED;
  4606. if (pwzUsername && pwzPassword)
  4607. {
  4608. // set the username and password
  4609. // and retry sendrequest
  4610. LPSTR pszUsername = DupW2A(pwzUsername);
  4611. LPSTR pszPassword = DupW2A(pwzPassword);
  4612. if (pszUsername)
  4613. {
  4614. InternetSetOption(_hRequest, INTERNET_OPTION_USERNAME, pszUsername, strlen(pszUsername)+1);
  4615. delete pszUsername;
  4616. }
  4617. if (pszPassword)
  4618. {
  4619. InternetSetOption(_hRequest, INTERNET_OPTION_PASSWORD, pszPassword, strlen(pszPassword)+1);
  4620. delete pszPassword;
  4621. }
  4622. // if we got username & pwd, only try once
  4623. _fProxyAuth ? _cbProxyAuthenticate = AUTHENTICATE_MAX :
  4624. _cbAuthenticate = AUTHENTICATE_MAX;
  4625. _hrINet = hr = RPC_E_RETRY;
  4626. PerfDbgLog2(tagCINet, this, "<2> _cbProxyAuthenticate:%d _cbAuthenticate:%d",
  4627. _cbProxyAuthenticate, _cbAuthenticate);
  4628. }
  4629. if ( (_hwndAuth || (_hwndAuth == (HWND)-1) )
  4630. && (_pCAuthData == NULL)
  4631. && (hr != RPC_E_RETRY) )
  4632. {
  4633. PProtAssert((_pCAuthData == NULL));
  4634. _pCAuthData = new CAuthData(this);
  4635. }
  4636. if ( (_hwndAuth || (_hwndAuth == (HWND)-1) )
  4637. && _pCAuthData
  4638. && (hr != RPC_E_RETRY) )
  4639. {
  4640. BOOL fRetry = FALSE;
  4641. BOOL fDeleteAuthData = TRUE;
  4642. DWORD dwFlags = ( FLAGS_ERROR_UI_FILTER_FOR_ERRORS | FLAGS_ERROR_UI_FLAGS_CHANGE_OPTIONS
  4643. | FLAGS_ERROR_UI_FLAGS_GENERATE_DATA | FLAGS_ERROR_UI_SERIALIZE_DIALOGS);
  4644. if ((dwBindF & BINDF_NO_UI) || (dwBindF & BINDF_SILENTOPERATION))
  4645. {
  4646. dwFlags |= FLAGS_ERROR_UI_FLAGS_NO_UI;
  4647. }
  4648. if (_hwndAuth == (HWND)-1)
  4649. {
  4650. _hwndAuth = 0;
  4651. }
  4652. do
  4653. {
  4654. _fProxyAuth ? _cbProxyAuthenticate++ : _cbAuthenticate++;
  4655. PerfDbgLog2(tagCINet, this, "<3> _cbProxyAuthenticate:%d _cbAuthenticate:%d",
  4656. _cbProxyAuthenticate, _cbAuthenticate);
  4657. dwError = InternetErrorDlg(_hwndAuth,_hRequest,ERROR_SUCCESS,dwFlags,(LPVOID *)&_pCAuthData);
  4658. switch (dwError)
  4659. {
  4660. case ERROR_CANCELLED :
  4661. // wininet should never return cancelled here
  4662. PProtAssert((FALSE));
  4663. case ERROR_SUCCESS :
  4664. // NOTE: succes and cancel means display the content according to ArthurBi
  4665. // continue reading data and show the 401 contained
  4666. _hrINet = hr = NOERROR;
  4667. break;
  4668. case ERROR_INTERNET_FORCE_RETRY :
  4669. _hrINet = hr = RPC_E_RETRY;
  4670. break;
  4671. case ERROR_INTERNET_DIALOG_PENDING :
  4672. // a dialog is up on another thread
  4673. // start wating on the callback
  4674. SetINetState(INetState_AUTHENTICATE);
  4675. SetStatePending(E_PENDING);
  4676. _fProxyAuth ? _cbProxyAuthenticate-- : _cbAuthenticate--;
  4677. PerfDbgLog2(tagCINet, this, "<4> _cbProxyAuthenticate:%d _cbAuthenticate:%d",
  4678. _cbProxyAuthenticate, _cbAuthenticate);
  4679. fDeleteAuthData = FALSE;
  4680. _hrINet = hr = E_PENDING;
  4681. break;
  4682. case ERROR_INTERNET_RETRY_DIALOG:
  4683. _fProxyAuth ? _cbProxyAuthenticate-- : _cbAuthenticate--;
  4684. PerfDbgLog2(tagCINet, this, "<5> _cbProxyAuthenticate:%d _cbAuthenticate:%d",
  4685. _cbProxyAuthenticate, _cbAuthenticate);
  4686. fRetry = TRUE;
  4687. break;
  4688. default:
  4689. _hrINet = hr = E_ACCESSDENIED;
  4690. break;
  4691. }
  4692. } while (fRetry);
  4693. if (fDeleteAuthData)
  4694. {
  4695. delete _pCAuthData;
  4696. _pCAuthData = NULL;
  4697. }
  4698. }
  4699. }
  4700. else
  4701. {
  4702. _hrINet = hr = E_ACCESSDENIED;
  4703. }
  4704. if (hr == RPC_E_RETRY)
  4705. {
  4706. _hrINet = NOERROR;
  4707. _fCompleted = FALSE;
  4708. _fSendAgain = TRUE;
  4709. if (IsA() == DLD_PROTOCOL_FTP || IsA() == DLD_PROTOCOL_GOPHER)
  4710. {
  4711. // Retry InternetOpenUrl using the updated auth info.
  4712. _fDoSimpleRetry = TRUE;
  4713. hr = INetAsyncOpenRequest();
  4714. }
  4715. else
  4716. {
  4717. hr = INetAsyncSendRequest();
  4718. }
  4719. }
  4720. else if (hr == E_PENDING)
  4721. {
  4722. // do nothing and wait for async completion
  4723. }
  4724. else if ( (hr != HRESULT_FROM_WIN32(ERROR_CANCELLED))
  4725. && (hr != NOERROR))
  4726. {
  4727. // set the error to access denied
  4728. _hrINet = hr = E_ACCESSDENIED;
  4729. }
  4730. }
  4731. if (pwzUsername)
  4732. {
  4733. delete pwzUsername;
  4734. }
  4735. if (pwzPassword)
  4736. {
  4737. delete pwzPassword;
  4738. }
  4739. PerfDbgLog1(tagCINet, this, "-CINet::AuthenticationRequest(hr:%lx)", hr);
  4740. DEBUG_LEAVE(hr);
  4741. return hr;
  4742. }
  4743. //+---------------------------------------------------------------------------
  4744. //
  4745. // Method: CINet::GetUrlCacheFilename
  4746. //
  4747. // Synopsis:
  4748. //
  4749. // Arguments: [szFilename] --
  4750. // [dwSize] --
  4751. //
  4752. // Returns:
  4753. //
  4754. // History: 2-28-96 JohannP (Johann Posch) Created
  4755. //
  4756. // Notes:
  4757. //
  4758. //----------------------------------------------------------------------------
  4759. HRESULT CINet::GetUrlCacheFilename(LPSTR szFilename, DWORD dwSize)
  4760. {
  4761. DEBUG_ENTER((DBG_APP,
  4762. Hresult,
  4763. "CINet::GetUrlCacheFilename",
  4764. "this=%#x, %#x, %#x",
  4765. this, szFilename, dwSize
  4766. ));
  4767. PerfDbgLog(tagCINet, this, "+CINet::GetUrlCacheFilename");
  4768. HRESULT hr = NOERROR;
  4769. BOOL fRet = FALSE;
  4770. DWORD dwSizeLocal = dwSize;
  4771. DWORD dwError = 0;
  4772. if (dwSize)
  4773. {
  4774. szFilename[0] = '\0';
  4775. }
  4776. if ( !(GetBindFlags() & BINDF_NOWRITECACHE)
  4777. || (GetBindFlags() & BINDF_NEEDFILE))
  4778. {
  4779. fRet = InternetQueryOption(_hRequest, INTERNET_OPTION_DATAFILE_NAME, szFilename, &dwSizeLocal);
  4780. if (!fRet && (GetBindFlags() & BINDF_NEEDFILE))
  4781. {
  4782. dwError = GetLastError();
  4783. hr = INET_E_DATA_NOT_AVAILABLE;
  4784. SetBindResult(dwError, hr);
  4785. if (dwSize)
  4786. {
  4787. szFilename[0] = '\0';
  4788. }
  4789. }
  4790. }
  4791. PerfDbgLog3(tagCINet, this, "-CINet::GetUrlCacheFilename (hr:%lx,fRet%d; szFilename:%s)", hr, fRet, szFilename);
  4792. DEBUG_LEAVE(hr);
  4793. return hr;
  4794. }
  4795. //+---------------------------------------------------------------------------
  4796. //
  4797. // Method: CINet::LockFile
  4798. //
  4799. // Synopsis:
  4800. //
  4801. // Arguments: [szFilename] --
  4802. // [dwSize] --
  4803. //
  4804. // Returns:
  4805. //
  4806. // History: 8-13-96 JohannP (Johann Posch) Created
  4807. //
  4808. // Notes:
  4809. //
  4810. //----------------------------------------------------------------------------
  4811. HRESULT CINet::LockFile(BOOL fRetrieve)
  4812. {
  4813. DEBUG_ENTER((DBG_APP,
  4814. Hresult,
  4815. "CINet::LockFile",
  4816. "this=%#x, %B",
  4817. this, fRetrieve
  4818. ));
  4819. PerfDbgLog(tagCINet, this, "+CINet::LockFile");
  4820. HRESULT hr = NOERROR;
  4821. BOOL fRet = FALSE;
  4822. if (fRetrieve)
  4823. {
  4824. DWORD dwCacheEntryInfoBufferSize = MAX_URL_SIZE + MAX_PATH + sizeof(INTERNET_CACHE_ENTRY_INFO) + 2;
  4825. INTERNET_CACHE_ENTRY_INFO *pCacheEntryInfo = (INTERNET_CACHE_ENTRY_INFO *)new CHAR [dwCacheEntryInfoBufferSize];
  4826. DWORD dwError = 0;
  4827. if ( (_fLocked == FALSE)
  4828. && (pCacheEntryInfo != NULL)
  4829. && (RetrieveUrlCacheEntryFileA( _pszFullURL, pCacheEntryInfo, &dwCacheEntryInfoBufferSize, 0)))
  4830. {
  4831. _fLocked = TRUE;
  4832. }
  4833. if (pCacheEntryInfo != NULL)
  4834. {
  4835. delete pCacheEntryInfo;
  4836. }
  4837. }
  4838. else if ((_hLockHandle == NULL) && _hRequest)
  4839. {
  4840. if (InternetLockRequestFile(_hRequest, &_hLockHandle))
  4841. {
  4842. PProtAssert((_hLockHandle));
  4843. }
  4844. }
  4845. PerfDbgLog2(tagCINet, this, "-CINet::LockFile (hr:%lx,fRet%d)", hr, fRet);
  4846. DEBUG_LEAVE(hr);
  4847. return hr;
  4848. }
  4849. //+---------------------------------------------------------------------------
  4850. //
  4851. // Method: CINet::UnlockFile
  4852. //
  4853. // Synopsis:
  4854. //
  4855. // Arguments: (none)
  4856. //
  4857. // Returns:
  4858. //
  4859. // History: 8-13-96 JohannP (Johann Posch) Created
  4860. //
  4861. // Notes:
  4862. //
  4863. //----------------------------------------------------------------------------
  4864. HRESULT CINet::UnlockFile()
  4865. {
  4866. DEBUG_ENTER((DBG_APP,
  4867. Hresult,
  4868. "CINet::UnlockFile",
  4869. "this=%#x",
  4870. this
  4871. ));
  4872. PerfDbgLog(tagCINet, this, "IN CINet::UnlockFile");
  4873. HRESULT hr = NOERROR;
  4874. if (_fLocked)
  4875. {
  4876. UnlockUrlCacheEntryFileA(_pszFullURL, 0);
  4877. _fLocked = FALSE;
  4878. }
  4879. else if (_hLockHandle)
  4880. {
  4881. if (InternetUnlockRequestFile(_hLockHandle))
  4882. {
  4883. _hLockHandle = NULL;
  4884. }
  4885. }
  4886. PerfDbgLog1(tagCINet, this, "-CINet::UnlockFile (hr:%lx)", hr);
  4887. DEBUG_LEAVE(hr);
  4888. return hr;
  4889. }
  4890. //+---------------------------------------------------------------------------
  4891. //
  4892. // Method: CINet::HResultFromInternetError
  4893. //
  4894. // Synopsis: maps the dwStatus ERROR_INTERNET_XXX do an hresult
  4895. //
  4896. // Arguments: [dwStatus] --
  4897. //
  4898. // Returns:
  4899. //
  4900. // History: 3-22-96 JohannP (Johann Posch) Created
  4901. //
  4902. // Notes:
  4903. //
  4904. //----------------------------------------------------------------------------
  4905. HRESULT CINet::HResultFromInternetError(DWORD dwStatus)
  4906. {
  4907. DEBUG_ENTER((DBG_APP,
  4908. Hresult,
  4909. "CINet::HResultFromInternetError",
  4910. "this=%#x, %#x",
  4911. this, dwStatus
  4912. ));
  4913. PerfDbgLog(tagCINet, this, "+CINet::HResultFromInternetError");
  4914. // dwResult is out of our know table
  4915. HRESULT hr = INET_E_DOWNLOAD_FAILURE;
  4916. ULONG ulIndex = dwStatus - INTERNET_ERROR_BASE;
  4917. PProtAssert((ulIndex > 0));
  4918. BOOL fTable1 = (ulIndex > 0 && ulIndex < sizeof(INetError)/sizeof(InterErrorToHResult));
  4919. DWORD dwTable2Size = sizeof(INetErrorExtended)/sizeof(InterErrorToHResult);
  4920. BOOL fTable2 = FALSE;
  4921. if (!fTable1)
  4922. {
  4923. fTable2 = (dwStatus <= INetErrorExtended[dwTable2Size].dwError);
  4924. }
  4925. if (fTable1)
  4926. {
  4927. // sequential table
  4928. hr = INetError[ulIndex].hresult;
  4929. }
  4930. else if (fTable2)
  4931. {
  4932. // walk the table
  4933. for (DWORD i = 0; i < dwTable2Size; i++)
  4934. {
  4935. if (INetErrorExtended[i].dwError == dwStatus)
  4936. {
  4937. hr = INetErrorExtended[i].hresult;
  4938. break;
  4939. }
  4940. }
  4941. }
  4942. PerfDbgLog1(tagCINet, this, "-CINet::HResultFromInternetError (hr:%lx)", hr);
  4943. DEBUG_LEAVE(hr);
  4944. return hr;
  4945. }
  4946. //+---------------------------------------------------------------------------
  4947. //
  4948. // Function: SetBindResult
  4949. //
  4950. // Synopsis:
  4951. //
  4952. // Arguments: [dwResult] --
  4953. //
  4954. // Returns:
  4955. //
  4956. // History: 5-10-96 JohannP (Johann Posch) Created
  4957. //
  4958. // Notes:
  4959. //
  4960. //----------------------------------------------------------------------------
  4961. HRESULT CINet::SetBindResult(DWORD dwResult, HRESULT hrSuggested)
  4962. {
  4963. DEBUG_ENTER((DBG_APP,
  4964. Hresult,
  4965. "CINet::SetBindResult",
  4966. "this=%#x, %#x, %#x",
  4967. this, dwResult, hrSuggested
  4968. ));
  4969. PerfDbgLog2(tagCINet, this, "+CINet::SetBindResult(dwResult:%ld, hrSuggested:%lx)", dwResult, hrSuggested);
  4970. HRESULT hr = NOERROR;
  4971. PProtAssert((_pszResult == NULL));
  4972. _pszResult = NULL;
  4973. _dwResult = dwResult;
  4974. // only find hresult in the mapping table
  4975. // if no erro was suggested
  4976. if (hrSuggested == NOERROR)
  4977. {
  4978. hr = _hrINet = HResultFromInternetError(_dwResult);
  4979. }
  4980. else
  4981. {
  4982. hr = _hrINet = hrSuggested;
  4983. }
  4984. PerfDbgLog3(tagCINet, this, "-CINet::SetBindResult (dwResult:%ld, _hrINet:%lx, hr:%lx)", dwResult, _hrINet, hr);
  4985. DEBUG_LEAVE(hr);
  4986. return hr;
  4987. }
  4988. //+---------------------------------------------------------------------------
  4989. //
  4990. // Method: CINet::GetBindResult
  4991. //
  4992. // Synopsis: returns the protocol specific error
  4993. //
  4994. // Arguments: [pclsidProtocol] --
  4995. // [pdwResult] --
  4996. // [DWORD] --
  4997. // [pdwReserved] --
  4998. //
  4999. // Returns:
  5000. //
  5001. // History: 4-16-96 JohannP (Johann Posch) Created
  5002. //
  5003. // Notes:
  5004. //
  5005. //----------------------------------------------------------------------------
  5006. HRESULT CINet::GetBindResult(CLSID *pclsidProtocol, DWORD *pdwResult, LPWSTR *pszResult, DWORD *pdwReserved)
  5007. {
  5008. DEBUG_ENTER((DBG_APP,
  5009. Hresult,
  5010. "CINet::GetBindResult",
  5011. "this=%#x, %#x, %#x, %#x, %#x",
  5012. this, pclsidProtocol, pdwResult, pszResult, pdwReserved
  5013. ));
  5014. PerfDbgLog(tagCINet, this, "+CINet::GetBindResult");
  5015. HRESULT hr = NOERROR;
  5016. PProtAssert((pclsidProtocol && pdwResult && pszResult));
  5017. *pclsidProtocol = _pclsidProtocol;
  5018. *pdwResult = _dwResult;
  5019. if (_pszResult)
  5020. {
  5021. // the client is supposted to free the string
  5022. *pszResult = new WCHAR [strlen(_pszResult) + 1];
  5023. if (*pszResult)
  5024. {
  5025. A2W(_pszResult, *pszResult, strlen(_pszResult));
  5026. }
  5027. }
  5028. else
  5029. {
  5030. *pszResult = NULL;
  5031. }
  5032. PerfDbgLog2(tagCINet, this, "-CINet::GetBindResult (dwResult:%lx, szStr:%ws)", _dwResult, pszResult);
  5033. DEBUG_LEAVE(hr);
  5034. return hr;
  5035. }
  5036. //+---------------------------------------------------------------------------
  5037. //
  5038. // Method: CINet::OnRedirected
  5039. //
  5040. // Synopsis: Called on wininet worker thread when wininet does a redirect.
  5041. // Sends notification to apartment thread.
  5042. //
  5043. // Arguments: [szNewUrl] --
  5044. //
  5045. // Returns:
  5046. //
  5047. // History: 4-17-96 JohannP (Johann Posch) Created
  5048. //
  5049. // Notes:
  5050. //
  5051. //----------------------------------------------------------------------------
  5052. HRESULT CINet::OnRedirect(LPSTR szNewUrl)
  5053. {
  5054. DEBUG_ENTER((DBG_APP,
  5055. Hresult,
  5056. "CINet::OnRedirect",
  5057. "this=%#x, %.80q",
  5058. this, szNewUrl
  5059. ));
  5060. PerfDbgLog1(tagCINet, this, "+CINet::OnRedirect (szNewUrl:%s)",szNewUrl);
  5061. HRESULT hr = NOERROR;
  5062. PProtAssert((szNewUrl && "WinINet reports redirect with redirect URL"));
  5063. if (szNewUrl)
  5064. {
  5065. _fRedirected = TRUE;
  5066. ReportNotification(BINDSTATUS_REDIRECTING, szNewUrl);
  5067. }
  5068. LONG lThirdParty;
  5069. if (IsThirdPartyUrl(szNewUrl))
  5070. {
  5071. lThirdParty = 1;
  5072. //MessageBoxA( 0, szNewUrl, "redirect: THIRDPARTY!", 0 );
  5073. InternetSetOption(_hRequest, INTERNET_OPTION_COOKIES_3RD_PARTY, &lThirdParty, sizeof(LONG));
  5074. }
  5075. else
  5076. {
  5077. lThirdParty = 0;
  5078. //MessageBoxA( 0, szNewUrl, "redirect: NOT THIRDPARTY!", 0 );
  5079. InternetSetOption(_hRequest, INTERNET_OPTION_COOKIES_3RD_PARTY, &lThirdParty, sizeof(LONG));
  5080. }
  5081. PerfDbgLog1(tagCINet, this, "-CINet::OnRedirect(hr:%lx)", hr);
  5082. DEBUG_LEAVE(hr);
  5083. return hr;
  5084. }
  5085. //+---------------------------------------------------------------------------
  5086. //
  5087. // Function: AppendToString
  5088. //
  5089. // Synopsis: Fast append of src to dest, reallocing of dest if necessary.
  5090. //
  5091. //
  5092. // Arguments: [IN/OUT] pszDest
  5093. // [IN/OUT] pcbDest
  5094. // [IN/OUT] pcbAlloced
  5095. // [IN] szSrc
  5096. // [IN] cbSrc
  5097. //
  5098. // Returns: TRUE/FALSE
  5099. //
  5100. // History: 6-2-97 Adriaan Canter (AdriaanC) Created
  5101. //
  5102. // Notes:
  5103. //
  5104. //----------------------------------------------------------------------------
  5105. BOOL AppendToString(LPSTR* pszDest, LPDWORD pcbDest,
  5106. LPDWORD pcbAlloced, LPSTR szSrc, DWORD cbSrc)
  5107. {
  5108. DEBUG_ENTER((DBG_APP,
  5109. Bool,
  5110. "AppendToString",
  5111. "%#x, %#x, %#x, %.80q, %#x",
  5112. pszDest, pcbDest, pcbAlloced, szSrc, cbSrc
  5113. ));
  5114. DWORD cbNew = *pcbDest + cbSrc;
  5115. if (cbNew > *pcbAlloced)
  5116. {
  5117. DWORD cbNewAlloc = *pcbAlloced + (cbSrc < MAX_PATH ? MAX_PATH : cbSrc);
  5118. LPSTR szNew = (LPSTR) new CHAR[cbNewAlloc];
  5119. if (!szNew)
  5120. {
  5121. DEBUG_LEAVE(FALSE);
  5122. return FALSE;
  5123. }
  5124. memcpy(szNew, *pszDest, *pcbDest);
  5125. delete [] *pszDest;
  5126. *pszDest = szNew;
  5127. *pcbAlloced = cbNewAlloc;
  5128. }
  5129. memcpy(*pszDest + *pcbDest, szSrc, cbSrc);
  5130. *pcbDest = cbNew;
  5131. DEBUG_LEAVE(TRUE);
  5132. return TRUE;
  5133. }
  5134. #ifdef unix
  5135. #include <sys/utsname.h>
  5136. #endif /* unix */
  5137. //+---------------------------------------------------------------------------
  5138. //
  5139. // Function: GetUserAgentString
  5140. //
  5141. // Synopsis: Gets the user agent string from the registry. If entry is
  5142. // the default string is returned.
  5143. //
  5144. // Arguments: (none)
  5145. //
  5146. // Returns: Allocated user agent string.
  5147. //
  5148. // History: 5-13-96 JohannP (Johann Posch) Created
  5149. // 6-02-97 AdriaanC (Adriaan Canter) Mods for mult reg entries.
  5150. //
  5151. // 6-25-97 AdriaanC (Adriaan Canter) Further mods described below.
  5152. //
  5153. // 12-18-98 Adriaanc (Adriaan Canter) - Versioned base values for
  5154. // IE5 and added a versioned IE5 location for token values
  5155. // which will get read in addition to common (IE4) location.
  5156. //
  5157. // Notes: User Agent string madness: We now generate the User Agent string
  5158. // from diverse entries in the registry. We first scan HKCU for base
  5159. // keys, falling back to HKLM if not found, or finally, defaults.
  5160. // For Pre and Post platform we now pickup all entries in both HKCU
  5161. // and HKLM. Finally, for back compatibility we enumerate a list of
  5162. // tokens (such as MSN 2.0, MSN 2.1, etc) from UA Tokens in the HKLM
  5163. // registry under Internet Settings, and if any of these tokens are
  5164. // found in the *old* HKCU location User Agent String we insert them
  5165. // into the pre platform portion of the generated user agent string.
  5166. // This was specifically done for MSN which has been fixing up the old
  5167. // registry location and depends on these tokens being found in the
  5168. // User Agent string.
  5169. //
  5170. //----------------------------------------------------------------------------
  5171. LPCSTR GetUserAgentString()
  5172. {
  5173. DEBUG_ENTER((DBG_APP,
  5174. String,
  5175. "GetUserAgentString",
  5176. NULL
  5177. ));
  5178. // Reg keys.
  5179. #define INTERNET_SETTINGS_KEY_SZ "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Internet Settings"
  5180. #define USER_AGENT_KEY_SZ "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\User Agent"
  5181. #define USER_AGENT_KEY5_SZ "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\5.0\\User Agent"
  5182. #define USER_AGENT_SZ "User Agent"
  5183. #define PRE_PLATFORM_KEY_SZ "Pre Platform"
  5184. #define POST_PLATFORM_KEY_SZ "Post Platform"
  5185. #define UA_TOKENS_KEY_SZ "UA Tokens"
  5186. // Base UA key strings.
  5187. #define UA_KEY_SZ NULL
  5188. #define COMPATIBLE_KEY_SZ "Compatible"
  5189. #define VERSION_KEY_SZ "Version"
  5190. #define PLATFORM_KEY_SZ "Platform"
  5191. // Base UA value strings.
  5192. #define UA_VAL_SZ "Mozilla/4.0"
  5193. #define COMPATIBLE_VAL_SZ "compatible"
  5194. #define VERSION_VAL_SZ "MSIE 6.0"
  5195. // Their lengths.
  5196. #define UA_VAL_LEN (sizeof(UA_VAL_SZ) - 1)
  5197. #define COMPATIBLE_VAL_LEN (sizeof(COMPATIBLE_VAL_SZ) - 1)
  5198. #define VERSION_VAL_LEN (sizeof(VERSION_VAL_SZ) - 1)
  5199. // If we encounter a failure in constructing the string, send this.
  5200. #ifdef _WIN64
  5201. #define DEFAULT_UA_STRING UA_VAL_SZ" ("COMPATIBLE_VAL_SZ"; "VERSION_VAL_SZ"; Win64)"
  5202. #else
  5203. #define DEFAULT_UA_STRING UA_VAL_SZ" ("COMPATIBLE_VAL_SZ"; "VERSION_VAL_SZ")"
  5204. #endif
  5205. // Used for backing up user agent string.
  5206. #define IE4_UA_BACKUP_FLAG "IE5_UA_Backup_Flag"
  5207. #define BACKUP_USER_AGENT_SZ "BackupUserAgent"
  5208. #define COMPAT_MODE_TOKEN "compat"
  5209. #define NUM_UA_KEYS 4
  5210. BOOL bSuccess = TRUE;
  5211. INT i, nBaseKeys;
  5212. DWORD dwIndex, dwType, cbBuf, cbUA, cbTotal;
  5213. LPSTR szUA, szBuf, pszWinVer;
  5214. OSVERSIONINFO osVersionInfo;
  5215. // Reg handles.
  5216. HKEY hHKCU_ISKey;
  5217. HKEY hHKCU_UAKey;
  5218. HKEY hHKLM_UAKey;
  5219. HKEY hHKCU_UA5Key;
  5220. HKEY hHKLM_UA5Key;
  5221. HKEY hPreKey;
  5222. HKEY hPostKey;
  5223. HKEY hTokensKey;
  5224. // Set all regkeys to invalid handle.
  5225. hHKCU_ISKey = hHKLM_UAKey = hHKCU_UAKey = hHKLM_UA5Key = hHKCU_UA5Key
  5226. = hPreKey = hPostKey = hTokensKey = (HKEY) INVALID_HANDLE_VALUE;
  5227. // The UA keys are iterated in loops below; Keep an array
  5228. // of pointers to the HKLMUA, HKCUUA, HKLMUA5 and HKCUUA5 locations
  5229. // to use as alias in the loop. NOTE!! - Do not change the ordering.
  5230. HKEY *phUAKeyArray[NUM_UA_KEYS];
  5231. phUAKeyArray[0] = &hHKLM_UAKey;
  5232. phUAKeyArray[1] = &hHKCU_UAKey;
  5233. phUAKeyArray[2] = &hHKLM_UA5Key;
  5234. phUAKeyArray[3] = &hHKCU_UA5Key;
  5235. // Platform strings.
  5236. LPSTR szWin32 = "Win32";
  5237. LPSTR szWin95 = "Windows 95";
  5238. LPSTR szWin98 = "Windows 98";
  5239. LPSTR szMillennium = "Windows 98; Win 9x 4.90";
  5240. LPSTR szWinNT = "Windows NT";
  5241. //for WinNT appended with version numbers
  5242. //Note: Limitation on total# of digits in Major+Minor versions=8.
  5243. //length = sizeof("Windows NT"+" "+majorverstring+"."+minorverstring
  5244. //Additional allowance is made for Win64 token.
  5245. #define WINNT_VERSION_STRING_MAX_LEN 32
  5246. char szWinNTVer[WINNT_VERSION_STRING_MAX_LEN];
  5247. #ifdef unix
  5248. CHAR szUnixPlatformName[SYS_NMLN*4+3+1]; // 4 substrings,3 spaces, 1 NULL
  5249. #endif /* unix */
  5250. // Arrays of base keys, values and lengths.
  5251. LPSTR szBaseKeys[] = {UA_KEY_SZ, COMPATIBLE_KEY_SZ, VERSION_KEY_SZ};
  5252. LPSTR szBaseValues[] = {UA_VAL_SZ, COMPATIBLE_VAL_SZ, VERSION_VAL_SZ};
  5253. DWORD cbBaseValues[] = {UA_VAL_LEN, COMPATIBLE_VAL_LEN, VERSION_VAL_LEN};
  5254. nBaseKeys = sizeof(szBaseKeys) / sizeof(LPSTR);
  5255. cbUA = 0;
  5256. cbTotal = cbBuf = MAX_PATH;
  5257. szBuf = szUA = 0;
  5258. // User agent string already exists.
  5259. if (g_pszUserAgentString != NULL)
  5260. {
  5261. szUA = g_pszUserAgentString;
  5262. goto End;
  5263. }
  5264. // Max size for any one field from registry is MAX_PATH.
  5265. szUA = new CHAR[MAX_PATH];
  5266. szBuf = new CHAR[MAX_PATH];
  5267. if (!szUA || !szBuf)
  5268. {
  5269. bSuccess = FALSE;
  5270. goto End;
  5271. }
  5272. // Open all 4 User Agent reg keys (HKLMUA, HKCUUA, HKLMUA5, HKCUUA5).
  5273. if (RegOpenKeyEx(HKEY_CURRENT_USER, USER_AGENT_KEY_SZ, 0, KEY_QUERY_VALUE, &hHKCU_UAKey) != ERROR_SUCCESS)
  5274. hHKCU_UAKey = (HKEY)INVALID_HANDLE_VALUE;
  5275. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, USER_AGENT_KEY_SZ, 0, KEY_QUERY_VALUE, &hHKLM_UAKey) != ERROR_SUCCESS)
  5276. hHKLM_UAKey = (HKEY)INVALID_HANDLE_VALUE;
  5277. if (RegOpenKeyEx(HKEY_CURRENT_USER, USER_AGENT_KEY5_SZ, 0, KEY_QUERY_VALUE, &hHKCU_UA5Key) != ERROR_SUCCESS)
  5278. hHKCU_UA5Key = (HKEY)INVALID_HANDLE_VALUE;
  5279. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, USER_AGENT_KEY5_SZ, 0, KEY_QUERY_VALUE, &hHKLM_UA5Key) != ERROR_SUCCESS)
  5280. hHKLM_UA5Key = (HKEY)INVALID_HANDLE_VALUE;
  5281. // Get user agent, compatible and version strings from IE 5.0 location.
  5282. // IE6 and on must revise this location.
  5283. for (i = 0; i < nBaseKeys; i++)
  5284. {
  5285. if ((hHKCU_UA5Key != INVALID_HANDLE_VALUE) && RegQueryValueEx(hHKCU_UA5Key, szBaseKeys[i],
  5286. NULL, &dwType, (LPBYTE) szBuf, &(cbBuf = MAX_PATH)) == ERROR_SUCCESS
  5287. && cbBuf > 1)
  5288. {
  5289. // Got from HKCU registry.
  5290. if (!(bSuccess = AppendToString(&szUA, &cbUA,
  5291. &cbTotal, szBuf, cbBuf - 1)))
  5292. goto End;
  5293. }
  5294. else if ((hHKLM_UA5Key != INVALID_HANDLE_VALUE) && RegQueryValueEx(hHKLM_UA5Key, szBaseKeys[i],
  5295. NULL, &dwType, (LPBYTE) szBuf, &(cbBuf = MAX_PATH)) == ERROR_SUCCESS
  5296. && cbBuf > 1)
  5297. {
  5298. // Got from HKLM registry.
  5299. if (!(bSuccess = AppendToString(&szUA, &cbUA,
  5300. &cbTotal, szBuf, cbBuf - 1)))
  5301. goto End;
  5302. }
  5303. else
  5304. {
  5305. // Got from defaults.
  5306. if (!(bSuccess = AppendToString(&szUA, &cbUA, &cbTotal,
  5307. szBaseValues[i], cbBaseValues[i])))
  5308. goto End;
  5309. }
  5310. // Formating.
  5311. if (!(bSuccess = AppendToString(&szUA, &cbUA,
  5312. &cbTotal, (i == 0 ? " (" : "; "), 2)))
  5313. goto End;
  5314. }
  5315. // Leave the four UA keys open; Proceed to open HKLM tokens key to scan
  5316. // to scan and open Internet Settings HKCU key to read legacy UA string.
  5317. // Tokens to scan for from the old registry location to include
  5318. // in the user agent string: These are enumerated from UA Tokens,
  5319. // scanned for in the old location and added to the pre platform.
  5320. if (hHKLM_UAKey != INVALID_HANDLE_VALUE)
  5321. RegOpenKeyEx(hHKLM_UAKey, UA_TOKENS_KEY_SZ, 0, KEY_QUERY_VALUE, &hTokensKey);
  5322. if (hTokensKey != INVALID_HANDLE_VALUE)
  5323. {
  5324. CHAR szOldUserAgentString[MAX_PATH];
  5325. // Read in the old user agent string from HKCU
  5326. RegOpenKeyEx(HKEY_CURRENT_USER, INTERNET_SETTINGS_KEY_SZ, 0, KEY_QUERY_VALUE, &hHKCU_ISKey);
  5327. if ((hHKCU_ISKey != INVALID_HANDLE_VALUE) && RegQueryValueEx(hHKCU_ISKey, USER_AGENT_SZ,
  5328. NULL, &dwType, (LPBYTE) szOldUserAgentString, &(cbBuf = MAX_PATH)) == ERROR_SUCCESS
  5329. && cbBuf > 1)
  5330. {
  5331. // Close the HKCU Internet Settings key.
  5332. RegCloseKey(hHKCU_ISKey);
  5333. hHKCU_ISKey = (HKEY) INVALID_HANDLE_VALUE;
  5334. // Got old user agent string from HKCU registry. Enumerate the values in UA Tokens
  5335. // and see if any exist in the old string and if so, add them to the current string.
  5336. dwIndex = 0;
  5337. #ifndef unix
  5338. while (RegEnumValue(hTokensKey, dwIndex++, szBuf, &(cbBuf = MAX_PATH - 4), /* sizeof(' ' + "; ") */
  5339. NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
  5340. {
  5341. // eg; find a token enumerated from UA Tokens
  5342. // Mozilla/4.0 (compatible; MSIE 4.0b2; MSN2.5; Windows NT)
  5343. // ^
  5344. // szBuf
  5345. if (cbBuf)
  5346. {
  5347. // Fix up token to include leading
  5348. // space and trailing semi-colon before strstr.
  5349. CHAR szToken[MAX_PATH];
  5350. szToken[0] = ' ';
  5351. memcpy(szToken+1, szBuf, cbBuf);
  5352. memcpy(szToken + 1 + cbBuf, "; ", sizeof("; "));
  5353. // Found a match - insert this token into user agent string.
  5354. if (strstr(szOldUserAgentString, szToken))
  5355. {
  5356. if (!(bSuccess = AppendToString(&szUA, &cbUA, &cbTotal, szBuf, cbBuf)))
  5357. goto End;
  5358. if (!(bSuccess = AppendToString(&szUA, &cbUA, &cbTotal, "; ", 2)))
  5359. goto End;
  5360. }
  5361. }
  5362. }
  5363. #endif /* !unix */
  5364. }
  5365. RegCloseKey(hTokensKey);
  5366. hTokensKey = (HKEY) INVALID_HANDLE_VALUE;
  5367. }
  5368. // Pre platform strings - get from HKCUUA, HKLMUA,
  5369. // HKLMUA5 and HKCUUA5 locations. These are additive;
  5370. // order is not important.
  5371. for (i = 0; i < NUM_UA_KEYS; i++)
  5372. {
  5373. if (*(phUAKeyArray[i]) == INVALID_HANDLE_VALUE)
  5374. continue;
  5375. RegOpenKeyEx(*(phUAKeyArray[i]),
  5376. PRE_PLATFORM_KEY_SZ, 0, KEY_QUERY_VALUE, &hPreKey);
  5377. if (hPreKey != INVALID_HANDLE_VALUE)
  5378. {
  5379. dwIndex = 0;
  5380. while (RegEnumValue(hPreKey, dwIndex++, szBuf, &(cbBuf = MAX_PATH),
  5381. NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
  5382. {
  5383. if (cbBuf)
  5384. {
  5385. // Got from registry and non null.
  5386. if (!(bSuccess = AppendToString(&szUA, &cbUA, &cbTotal, szBuf, cbBuf)))
  5387. goto End;
  5388. if (!(bSuccess = AppendToString(&szUA, &cbUA, &cbTotal, "; ", 2)))
  5389. goto End;
  5390. }
  5391. cbBuf = MAX_PATH;
  5392. }
  5393. // Close pre platform key; User agent keys still open.
  5394. RegCloseKey(hPreKey);
  5395. hPreKey = (HKEY) INVALID_HANDLE_VALUE;
  5396. }
  5397. }
  5398. // Platform string. This is read from the IE 5.0 location only. IE6 and later
  5399. // must revise this. If no platform value read from registry, get from OS.
  5400. if (hHKCU_UA5Key != INVALID_HANDLE_VALUE && RegQueryValueEx(hHKCU_UA5Key, PLATFORM_KEY_SZ,
  5401. NULL, &dwType, (LPBYTE) szBuf, &(cbBuf = MAX_PATH)) == ERROR_SUCCESS)
  5402. {
  5403. // Got from HKCU.
  5404. if (!(bSuccess = AppendToString(&szUA, &cbUA, &cbTotal, szBuf, cbBuf -1)))
  5405. goto End;
  5406. }
  5407. else if (hHKLM_UA5Key != INVALID_HANDLE_VALUE && RegQueryValueEx(hHKLM_UA5Key, PLATFORM_KEY_SZ,
  5408. NULL, &dwType, (LPBYTE) szBuf, &(cbBuf = MAX_PATH)) == ERROR_SUCCESS)
  5409. {
  5410. // Got from HKLM
  5411. if (!(bSuccess = AppendToString(&szUA, &cbUA, &cbTotal, szBuf, cbBuf -1)))
  5412. goto End;
  5413. }
  5414. else
  5415. {
  5416. // Couldn't get User Agent value from registry.
  5417. // Set the default value.
  5418. osVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  5419. if (GetVersionEx(&osVersionInfo))
  5420. {
  5421. #ifndef unix
  5422. // Platform ID is either Win95 or WinNT.
  5423. if(VER_PLATFORM_WIN32_NT == osVersionInfo.dwPlatformId)
  5424. {
  5425. Assert(osVersionInfo.dwMajorVersion < 10000 &&
  5426. osVersionInfo.dwMinorVersion < 10000);
  5427. /* Check for WIN64, adding another token if necessary */
  5428. LPSTR szWin64Token = "; Win64";
  5429. LPSTR szWow64Token = "; WOW64";
  5430. SYSTEM_INFO SysInfo;
  5431. GetSystemInfo(&SysInfo);
  5432. bool fWin64 = ((SysInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64) ||
  5433. (SysInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_IA64));
  5434. bool fWow64 = FALSE;
  5435. // There is no easy way to determine whether a 32-bit app is running on a 32-bit OS
  5436. // or Wow64. The recommended approach (Q275217) to determine this is to see if
  5437. // GetSystemWow64DirectoryA is implemented in kernel32.dll and to see if the function
  5438. // succeeds. If it succeeds, then we're running on a 64-bit processor.
  5439. if (!fWin64 && SysInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL)
  5440. {
  5441. char directoryPath[MAX_PATH];
  5442. HMODULE hModule;
  5443. GetSystemWow64DirectoryPtr func;
  5444. hModule = GetModuleHandle("kernel32.dll");
  5445. func = (GetSystemWow64DirectoryPtr) GetProcAddress(hModule, "GetSystemWow64DirectoryA");
  5446. if (func && func(directoryPath, sizeof(directoryPath)))
  5447. {
  5448. fWow64 = TRUE;
  5449. }
  5450. }
  5451. LPSTR sz64Str = NULL;
  5452. if( fWin64)
  5453. sz64Str = szWin64Token;
  5454. else if( fWow64)
  5455. sz64Str = szWow64Token;
  5456. else
  5457. sz64Str = "";
  5458. memset(szWinNTVer, 0, WINNT_VERSION_STRING_MAX_LEN);
  5459. wsprintfA(szWinNTVer,
  5460. "%s %u.%u%s",
  5461. szWinNT,
  5462. osVersionInfo.dwMajorVersion,
  5463. osVersionInfo.dwMinorVersion,
  5464. sz64Str);
  5465. pszWinVer = szWinNTVer;
  5466. }
  5467. else
  5468. {
  5469. if(osVersionInfo.dwMinorVersion >= 10)
  5470. {
  5471. if(osVersionInfo.dwMinorVersion >= 90)
  5472. {
  5473. // Millennium
  5474. pszWinVer = szMillennium;
  5475. }
  5476. else
  5477. {
  5478. // Win98
  5479. pszWinVer = szWin98;
  5480. }
  5481. }
  5482. else
  5483. {
  5484. // Win95
  5485. pszWinVer = szWin95;
  5486. }
  5487. }
  5488. #else
  5489. struct utsname uName;
  5490. if(uname(&uName) > -1)
  5491. {
  5492. strcpy(szUnixPlatformName,uName.sysname);
  5493. strcat(szUnixPlatformName," ");
  5494. strcat(szUnixPlatformName,uName.release);
  5495. strcat(szUnixPlatformName," ");
  5496. strcat(szUnixPlatformName,uName.machine);
  5497. strcat(szUnixPlatformName,"; X11");
  5498. pszWinVer = &szUnixPlatformName[0];
  5499. }
  5500. else
  5501. pszWinVer = "Generic Unix";
  5502. #endif /* unix */
  5503. }
  5504. else
  5505. {
  5506. // GetVersionEx failed! - set Platform to Win32.
  5507. pszWinVer = szWin32;
  5508. }
  5509. if (!(bSuccess = AppendToString(&szUA, &cbUA, &cbTotal,
  5510. pszWinVer, strlen(pszWinVer))))
  5511. goto End;
  5512. }
  5513. // Post platform strings - get from HKCUUA, HKLMUA,
  5514. // HKLMUA5 and HKCUUA5 locations. These are additive;
  5515. // order is not important. Special case the IE4
  5516. // compat token. IE6 and later must do this also.
  5517. for (i = 0; i < NUM_UA_KEYS; i++)
  5518. {
  5519. if (*(phUAKeyArray[i]) == INVALID_HANDLE_VALUE)
  5520. continue;
  5521. RegOpenKeyEx(*(phUAKeyArray[i]),
  5522. POST_PLATFORM_KEY_SZ, 0, KEY_QUERY_VALUE, &hPostKey);
  5523. if (hPostKey != INVALID_HANDLE_VALUE)
  5524. {
  5525. dwIndex = 0;
  5526. while (RegEnumValue(hPostKey, dwIndex++, szBuf, &(cbBuf = MAX_PATH),
  5527. NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
  5528. {
  5529. // We need to special case the IE4 compat mode token in the
  5530. // first two keys in phUAKeyArray[];
  5531. if (cbBuf && ((i > 1) || strcmp(szBuf, COMPAT_MODE_TOKEN)))
  5532. {
  5533. // Got from registry and non null.
  5534. if (!(bSuccess = AppendToString(&szUA, &cbUA, &cbTotal, "; ", 2)))
  5535. goto End;
  5536. if (!(bSuccess = AppendToString(&szUA, &cbUA, &cbTotal, szBuf, cbBuf)))
  5537. goto End;
  5538. }
  5539. cbBuf = MAX_PATH;
  5540. }
  5541. // Close post platform key; User agent keys still open.
  5542. RegCloseKey(hPostKey);
  5543. hPostKey = (HKEY) INVALID_HANDLE_VALUE;
  5544. }
  5545. }
  5546. // Terminate with ")\0"
  5547. if (!(bSuccess = AppendToString(&szUA, &cbUA, &cbTotal, ")", 2)))
  5548. goto End;
  5549. for (i = 0; i < NUM_UA_KEYS; i++)
  5550. {
  5551. if (*(phUAKeyArray[i]) != INVALID_HANDLE_VALUE)
  5552. {
  5553. RegCloseKey(*(phUAKeyArray[i]));
  5554. *(phUAKeyArray[i]) = (HKEY) INVALID_HANDLE_VALUE;
  5555. }
  5556. }
  5557. // Finally, write out the generated user agent string in the old location.
  5558. if (bSuccess)
  5559. {
  5560. // Remember the computed user agent string for later.
  5561. g_pszUserAgentString = szUA;
  5562. }
  5563. End:
  5564. // Cleanup.
  5565. delete [] szBuf;
  5566. if (!bSuccess)
  5567. {
  5568. delete [] szUA;
  5569. DEBUG_LEAVE(DEFAULT_UA_STRING);
  5570. return DEFAULT_UA_STRING;
  5571. }
  5572. DEBUG_LEAVE(szUA);
  5573. return szUA;
  5574. }
  5575. //+---------------------------------------------------------------------------
  5576. //
  5577. // Method: ObtainUserAgentString
  5578. //
  5579. // Synopsis:
  5580. //
  5581. // Returns:
  5582. //
  5583. // History: 08-07-1997 DanpoZ (Danpo Zhang) Created
  5584. //
  5585. // Notes:
  5586. //
  5587. //----------------------------------------------------------------------------
  5588. STDAPI ObtainUserAgentString(DWORD dwOption, LPSTR pszUAOut, DWORD *cbSize )
  5589. {
  5590. DEBUG_ENTER_API((DBG_API,
  5591. Hresult,
  5592. "ObtainUserAgentString",
  5593. "%#x, %#x, %#x",
  5594. dwOption, pszUAOut, cbSize
  5595. ));
  5596. // since GetUserAgentString may change some global variable,
  5597. // this API needs to add a global mutex to protect them
  5598. CLock lck(g_mxsSession);
  5599. HRESULT hr = NOERROR;
  5600. if( pszUAOut && cbSize )
  5601. {
  5602. LPSTR pcszUA = (LPSTR)GetUserAgentString();
  5603. DWORD cbLen = strlen(pcszUA);
  5604. if( *cbSize <= cbLen )
  5605. {
  5606. hr = E_OUTOFMEMORY;
  5607. }
  5608. else
  5609. {
  5610. strcpy(pszUAOut, pcszUA);
  5611. }
  5612. *cbSize = cbLen + 1;
  5613. }
  5614. else
  5615. {
  5616. hr = E_INVALIDARG;
  5617. }
  5618. DEBUG_LEAVE_API(hr);
  5619. return hr;
  5620. }
  5621. //+---------------------------------------------------------------------------
  5622. //
  5623. // Method: CINet::InternetAuthNotifyCallback
  5624. //
  5625. // Synopsis:
  5626. //
  5627. // Arguments: [dwContext] --
  5628. // [dwAction] --
  5629. // [lpReserved] --
  5630. //
  5631. // Returns:
  5632. //
  5633. // History: 10-10-1996 JohannP (Johann Posch) Created
  5634. //
  5635. // Notes:
  5636. //
  5637. //----------------------------------------------------------------------------
  5638. DWORD CALLBACK CINet::InternetAuthNotifyCallback(DWORD_PTR dwContext, DWORD dwAction, LPVOID lpReserved)
  5639. {
  5640. DEBUG_ENTER((DBG_APP,
  5641. Dword,
  5642. "CINet::InternetAuthNotifyCallback",
  5643. "%#x, %#x, %#x",
  5644. dwContext, dwAction, lpReserved
  5645. ));
  5646. // If this is a request, then we know the cookie type
  5647. CINet *pCINet = (CINet *) dwContext;
  5648. PerfDbgLog2(tagCINet, pCINet, "+CINet::InternetAuthNotifyCallback Action:%ld, State:%ld",
  5649. dwAction, pCINet->_INState);
  5650. PProtAssert((lpReserved == NULL));
  5651. DWORD dwRes = ERROR_SUCCESS;
  5652. switch (dwAction)
  5653. {
  5654. case ERROR_SUCCESS :
  5655. // should never be returned here
  5656. PProtAssert((FALSE));
  5657. case ERROR_CANCELLED :
  5658. // NOTE: succes and cancel means display the content according to ArthurBi
  5659. // continue reading data and show the 401 contained
  5660. pCINet->_hrINet = NOERROR;
  5661. // Why do we inc the count here??
  5662. pCINet->_fProxyAuth ? pCINet->_cbProxyAuthenticate++ : pCINet->_cbAuthenticate++;
  5663. break;
  5664. case ERROR_INTERNET_RETRY_DIALOG:
  5665. pCINet->_hrINet = INET_E_AUTHENTICATION_REQUIRED;
  5666. break;
  5667. case ERROR_INTERNET_FORCE_RETRY :
  5668. pCINet->_hrINet = RPC_E_RETRY;
  5669. pCINet->_fProxyAuth ? pCINet->_cbProxyAuthenticate++ : pCINet->_cbAuthenticate++;
  5670. break;
  5671. default:
  5672. pCINet->_hrINet = E_ACCESSDENIED;
  5673. break;
  5674. }
  5675. pCINet->OnINetAuthenticate(dwAction);
  5676. PerfDbgLog2(tagCINet, pCINet, "-CINet::InternetAuthNotifyCallback (pCINet->_hrINet:%lx, dwResult:%lx)", pCINet->_hrINet,dwRes);
  5677. DEBUG_LEAVE(dwRes);
  5678. return dwRes;
  5679. }
  5680. //+---------------------------------------------------------------------------
  5681. //
  5682. // Method: CINet::OnINetAuthenticate
  5683. //
  5684. // Synopsis:
  5685. //
  5686. // Arguments: [dwResult] --
  5687. //
  5688. // Returns:
  5689. //
  5690. // History: 10-10-1996 JohannP (Johann Posch) Created
  5691. //
  5692. // Notes:
  5693. //
  5694. //----------------------------------------------------------------------------
  5695. HRESULT CINet::OnINetAuthenticate(DWORD dwResult)
  5696. {
  5697. DEBUG_ENTER((DBG_APP,
  5698. Hresult,
  5699. "CINet::OnINetAuthenticate",
  5700. "this=%#x, %#x",
  5701. this, dwResult
  5702. ));
  5703. PerfDbgLog(tagCINet, this, "+CINet::OnINetAuthenticate");
  5704. HRESULT hr = NOERROR;
  5705. PProtAssert((GetStatePending() == E_PENDING));
  5706. // set state to normal - no pending transaction
  5707. SetStatePending(NOERROR);
  5708. PProtAssert((_INState == INetState_AUTHENTICATE));
  5709. if (dwResult)
  5710. {
  5711. TransitState(INetState_AUTHENTICATE, TRUE);
  5712. }
  5713. PerfDbgLog1(tagCINet, this, "-CINet::OnINetAuthenticate (hr:%lx)", hr);
  5714. DEBUG_LEAVE(hr);
  5715. return hr;
  5716. }
  5717. //+---------------------------------------------------------------------------
  5718. //
  5719. // Method: CINet::INetAuthenticate
  5720. //
  5721. // Synopsis:
  5722. //
  5723. // Arguments: (none)
  5724. //
  5725. // Returns:
  5726. //
  5727. // History: 10-10-1996 JohannP (Johann Posch) Created
  5728. //
  5729. // Notes:
  5730. //
  5731. //----------------------------------------------------------------------------
  5732. HRESULT CINet::INetAuthenticate()
  5733. {
  5734. DEBUG_ENTER((DBG_APP,
  5735. Hresult,
  5736. "CINet::INetAuthenticate",
  5737. "this=%#x",
  5738. this
  5739. ));
  5740. PerfDbgLog(tagCINet, this, "+CINet::INetAuthenticate");
  5741. PProtAssert((GetStatePending() == NOERROR));
  5742. HRESULT hr = NOERROR;
  5743. DWORD dwOperation;
  5744. PProtAssert((GetStatePending() == NOERROR));
  5745. if (_hrINet == INET_E_AUTHENTICATION_REQUIRED)
  5746. {
  5747. // bring up the internet errro dialog
  5748. hr = AuthenticationRequest();
  5749. if ((hr != NOERROR) && (hr != E_PENDING))
  5750. {
  5751. _hrError = INET_E_AUTHENTICATION_REQUIRED;
  5752. }
  5753. else
  5754. {
  5755. _hrError = INET_E_OK;
  5756. }
  5757. }
  5758. if (hr == NOERROR)
  5759. {
  5760. if (_hrINet == RPC_E_RETRY)
  5761. {
  5762. // retry the send/request
  5763. _hrINet = NOERROR;
  5764. _fCompleted = FALSE;
  5765. _fSendAgain = TRUE;
  5766. hr = INetAsyncSendRequest();
  5767. }
  5768. else if (_hrINet == NOERROR)
  5769. {
  5770. hr = QueryStatusOnResponseDefault(0);
  5771. if( hr == NOERROR )
  5772. {
  5773. hr = QueryHeaderOnResponse();
  5774. if (hr == NOERROR)
  5775. {
  5776. // read more data from wininet
  5777. hr = INetRead();
  5778. }
  5779. }
  5780. }
  5781. else
  5782. {
  5783. // this will report the hresult return from the dialog
  5784. hr = _hrINet;
  5785. }
  5786. }
  5787. PerfDbgLog1(tagCINet, this, "-CINet::INetAuthenticate (hr:%lx)", hr);
  5788. DEBUG_LEAVE(hr);
  5789. return hr;
  5790. }
  5791. //+---------------------------------------------------------------------------
  5792. //
  5793. // Method: CINet::INetResumeAsyncRequest
  5794. //
  5795. // Synopsis:
  5796. //
  5797. // Arguments: (none)
  5798. //
  5799. // Returns:
  5800. //
  5801. // History: 1-27-96 JohannP (Johann Posch) Created
  5802. //
  5803. // Notes:
  5804. //
  5805. //----------------------------------------------------------------------------
  5806. HRESULT CINet::INetResumeAsyncRequest(DWORD dwResultCode)
  5807. {
  5808. DEBUG_ENTER((DBG_APP,
  5809. Hresult,
  5810. "CINet::INetResumeAsyncRequest",
  5811. "this=%#x, %#x",
  5812. this, dwResultCode
  5813. ));
  5814. PerfDbgLog(tagCINet, this, "+CINet::INetResumeAsyncRequest");
  5815. HRESULT hr = NOERROR;
  5816. BOOL fRestarted;
  5817. BOOL fRet;
  5818. PProtAssert((GetStatePending() == NOERROR));
  5819. SetINetState(INetState_SEND_REQUEST);
  5820. {
  5821. SetStatePending(E_PENDING);
  5822. fRet = ResumeSuspendedDownload(_hRequest,
  5823. dwResultCode
  5824. );
  5825. if (fRet == FALSE)
  5826. {
  5827. dwLstError = GetLastError();
  5828. if (dwLstError == ERROR_IO_PENDING)
  5829. {
  5830. // wait async for the handle
  5831. hr = E_PENDING;
  5832. }
  5833. else
  5834. {
  5835. SetStatePending(NOERROR);
  5836. hr = _hrError = INET_E_DOWNLOAD_FAILURE;
  5837. SetBindResult(dwLstError,hr);
  5838. PerfDbgLog3(tagCINet, this, "CINet::INetResumeAsyncRequest (fRet:%d, _hrError:%lx, LstError:%ld)", fRet, _hrError, dwLstError);
  5839. }
  5840. }
  5841. else
  5842. {
  5843. SetStatePending(NOERROR);
  5844. }
  5845. }
  5846. if (_hrError != INET_E_OK)
  5847. {
  5848. // we need to terminate here
  5849. ReportResultAndStop(hr);
  5850. }
  5851. PerfDbgLog1(tagCINet, this, "-CINet::INetResumeAsyncRequest (hr:%lx)", hr);
  5852. DEBUG_LEAVE(hr);
  5853. return hr;
  5854. }
  5855. //+---------------------------------------------------------------------------
  5856. //
  5857. // Method: CINet::INetDisplayUI
  5858. //
  5859. // Synopsis:
  5860. //
  5861. // Arguments: (none)
  5862. //
  5863. // Returns:
  5864. //
  5865. // History: 10-10-1996 JohannP (Johann Posch) Created
  5866. //
  5867. // Notes:
  5868. //
  5869. //----------------------------------------------------------------------------
  5870. HRESULT CINet::INetDisplayUI()
  5871. {
  5872. DEBUG_ENTER((DBG_APP,
  5873. Hresult,
  5874. "CINet::INetDisplayUI",
  5875. "this=%#x",
  5876. this
  5877. ));
  5878. PerfDbgLog(tagCINet, this, "+CINet::INetDisplayUI");
  5879. PProtAssert((GetStatePending() == NOERROR));
  5880. HRESULT hr = NOERROR;
  5881. DWORD dwOperation;
  5882. DWORD dwResultCode = ERROR_SUCCESS;
  5883. PProtAssert((GetStatePending() == NOERROR));
  5884. DWORD dwBindF = GetBindFlags();
  5885. if (_hrINet == INET_E_AUTHENTICATION_REQUIRED)
  5886. {
  5887. HWND hwnd = 0;
  5888. hr = NOERROR;
  5889. // Get a window handle. QueryService on IWindowForBindingUI
  5890. // to get a window object first if necessary.
  5891. if (_pWindow == NULL)
  5892. {
  5893. hr = QueryService(IID_IWindowForBindingUI, (void **) &_pWindow);
  5894. }
  5895. // If we don't already have a window handle, get one from the interface.
  5896. if (!hwnd && _pWindow)
  5897. {
  5898. hr = _pWindow->GetWindow(IID_IHttpSecurity, &hwnd);
  5899. PProtAssert(( (hr == S_FALSE) && (hwnd == NULL)
  5900. || (hr == S_OK) && (hwnd != NULL)));
  5901. }
  5902. if (hwnd && (hr == S_OK))
  5903. {
  5904. DWORD dwFlags = FLAGS_ERROR_UI_SERIALIZE_DIALOGS;
  5905. if ((dwBindF & BINDF_NO_UI) || (dwBindF & BINDF_SILENTOPERATION))
  5906. {
  5907. dwFlags |= FLAGS_ERROR_UI_FLAGS_NO_UI;
  5908. }
  5909. dwResultCode =
  5910. InternetErrorDlg( hwnd, _hRequest, _dwSendRequestResult, dwFlags, &_lpvExtraSendRequestResult);
  5911. if ( dwResultCode == ERROR_CANCELLED || dwResultCode == ERROR_SUCCESS )
  5912. {
  5913. // hack-hack alert, if _lpvExtraSendRequestResult non-null we change behavior
  5914. if ( !(dwResultCode == ERROR_SUCCESS && _lpvExtraSendRequestResult != NULL) )
  5915. {
  5916. dwResultCode = ERROR_INTERNET_OPERATION_CANCELLED;
  5917. }
  5918. }
  5919. _hrINet = RPC_E_RETRY;
  5920. hr = NOERROR;
  5921. }
  5922. else if (_dwSendRequestResult == ERROR_HTTP_COOKIE_NEEDS_CONFIRMATION ||
  5923. _dwSendRequestResult == ERROR_HTTP_COOKIE_NEEDS_CONFIRMATION_EX)
  5924. {
  5925. //fix to prevent heap trashing in wininet.b#86959
  5926. dwResultCode = ERROR_HTTP_COOKIE_DECLINED;
  5927. _hrINet = RPC_E_RETRY;
  5928. hr = NOERROR;
  5929. }
  5930. if ((hr != NOERROR) && (hr != E_PENDING))
  5931. {
  5932. _hrError = INET_E_AUTHENTICATION_REQUIRED;
  5933. }
  5934. else
  5935. {
  5936. _hrError = INET_E_OK;
  5937. }
  5938. }
  5939. if (hr == NOERROR)
  5940. {
  5941. if (_hrINet == RPC_E_RETRY)
  5942. {
  5943. // retry the send/request
  5944. _hrINet = NOERROR;
  5945. // hack-arama around to allow CD-ROM dialog to still work
  5946. if ( _dwSendRequestResult == ERROR_INTERNET_INSERT_CDROM )
  5947. {
  5948. hr = INetAsyncSendRequest();
  5949. }
  5950. else
  5951. {
  5952. hr = INetResumeAsyncRequest(dwResultCode);
  5953. }
  5954. }
  5955. else
  5956. {
  5957. // this will report the hresult return from the dialog
  5958. hr = _hrINet;
  5959. }
  5960. }
  5961. PerfDbgLog1(tagCINet, this, "-CINet::INetDisplayUI (hr:%lx)", hr);
  5962. DEBUG_LEAVE(hr);
  5963. return hr;
  5964. }
  5965. //+---------------------------------------------------------------------------
  5966. //
  5967. // Method: CINet::INetSeek
  5968. //
  5969. // Synopsis:
  5970. //
  5971. // Arguments: [DWORD] --
  5972. // [ULARGE_INTEGER] --
  5973. // [plibNewPosition] --
  5974. //
  5975. // Returns:
  5976. //
  5977. // History: 10-29-1996 JohannP (Johann Posch) Created
  5978. //
  5979. // Notes:
  5980. //
  5981. //----------------------------------------------------------------------------
  5982. HRESULT CINet::INetSeek(LARGE_INTEGER dlibMove,DWORD dwOrigin,ULARGE_INTEGER *plibNewPosition)
  5983. {
  5984. DEBUG_ENTER((DBG_APP,
  5985. Hresult,
  5986. "CINet::INetSeek",
  5987. "this=%#x, %#x, %#x, %#x",
  5988. this, dlibMove, dwOrigin, plibNewPosition
  5989. ));
  5990. PerfDbgLog(tagCINet, this, "+CINet::INetSeek");
  5991. HRESULT hr = E_FAIL;
  5992. // each protocol has to overwrite this method if
  5993. // seek is supported
  5994. DWORD dwResult = InternetSetFilePointer(
  5995. _hRequest
  5996. ,dlibMove.LowPart
  5997. ,0
  5998. ,dwOrigin
  5999. ,0
  6000. );
  6001. PerfDbgLog1(tagCINet, this, "-CINet::INetSeek (hr:%lx)", hr);
  6002. DEBUG_LEAVE(hr);
  6003. return hr;
  6004. }
  6005. //+---------------------------------------------------------------------------
  6006. //
  6007. // Method: CINet::IsUpLoad
  6008. //
  6009. // Synopsis:
  6010. //
  6011. // Arguments: (none)
  6012. //
  6013. // Returns:
  6014. //
  6015. // History: 4-28-1997 JohannP (Johann Posch) Created
  6016. //
  6017. // Notes:
  6018. //
  6019. //----------------------------------------------------------------------------
  6020. BOOL CINet::IsUpLoad()
  6021. {
  6022. DEBUG_ENTER((DBG_APP,
  6023. Bool,
  6024. "CINet::IsUpLoad",
  6025. "this=%#x",
  6026. this
  6027. ));
  6028. BINDINFO *pBndInfo = GetBindInfo();
  6029. BOOL fRet = ( (pBndInfo->dwBindVerb != BINDVERB_GET)
  6030. && (pBndInfo->stgmedData.tymed == TYMED_ISTREAM)
  6031. && !_fCompleted
  6032. && !_fRedirected);
  6033. DEBUG_LEAVE(fRet);
  6034. return fRet;
  6035. }
  6036. //+---------------------------------------------------------------------------
  6037. //
  6038. // Method: CINet::CPrivUnknown::QueryInterface
  6039. //
  6040. // Synopsis:
  6041. //
  6042. // Arguments: [riid] --
  6043. // [ppvObj] --
  6044. //
  6045. // Returns:
  6046. //
  6047. // History: 10-29-1996 JohannP (Johann Posch) Created
  6048. //
  6049. // Notes:
  6050. //
  6051. //----------------------------------------------------------------------------
  6052. STDMETHODIMP CINet::CPrivUnknown::QueryInterface(REFIID riid, void **ppvObj)
  6053. {
  6054. DEBUG_ENTER((DBG_APP,
  6055. Hresult,
  6056. "CINet::CPrivUnknown::IUnknown::QueryInterface",
  6057. "this=%#x, %#x, %#x",
  6058. this, &riid, ppvObj
  6059. ));
  6060. VDATEPTROUT(ppvObj, void *);
  6061. VDATETHIS(this);
  6062. HRESULT hr = NOERROR;
  6063. PerfDbgLog(tagCINet, this, "+CINet::CPrivUnknown::QueryInterface");
  6064. CINet *pCINet = GETPPARENT(this, CINet, _Unknown);
  6065. *ppvObj = NULL;
  6066. if ((riid == IID_IUnknown) || (riid == IID_IOInetProtocol) || (riid == IID_IOInetProtocolRoot) )
  6067. {
  6068. *ppvObj = (IOInetProtocol *) pCINet;
  6069. pCINet->AddRef();
  6070. }
  6071. else if ( ( IsEqualIID(riid, IID_IWinInetInfo)||
  6072. IsEqualIID(riid, IID_IWinInetHttpInfo) ) &&
  6073. ( !IsEqualIID(CLSID_FileProtocol, pCINet->_pclsidProtocol) ) )
  6074. {
  6075. *ppvObj = (void FAR *) (IWinInetHttpInfo *)pCINet;
  6076. pCINet->AddRef();
  6077. }
  6078. else if (riid == IID_IOInetThreadSwitch)
  6079. {
  6080. *ppvObj = (IOInetThreadSwitch *)pCINet;
  6081. pCINet->AddRef();
  6082. }
  6083. else
  6084. {
  6085. hr = E_NOINTERFACE;
  6086. }
  6087. PerfDbgLog1(tagCINet, this, "-CINet::CPrivUnknown::QueryInterface (hr:%lx)", hr);
  6088. DEBUG_LEAVE(hr);
  6089. return hr;
  6090. }
  6091. //+---------------------------------------------------------------------------
  6092. //
  6093. // Function: CINet::CPrivUnknown::AddRef
  6094. //
  6095. // Synopsis:
  6096. //
  6097. // Arguments: [ULONG] --
  6098. //
  6099. // Returns:
  6100. //
  6101. // History: 10-29-1996 JohannP (Johann Posch) Created
  6102. //
  6103. // Notes:
  6104. //
  6105. //----------------------------------------------------------------------------
  6106. STDMETHODIMP_(ULONG) CINet::CPrivUnknown::AddRef(void)
  6107. {
  6108. DEBUG_ENTER((DBG_APP,
  6109. Dword,
  6110. "CINet::CPrivUnknown::IUnknown::AddRef",
  6111. "this=%#x",
  6112. this
  6113. ));
  6114. PerfDbgLog(tagCINet, this, "+CINet::CPrivUnknown::AddRef");
  6115. LONG lRet = ++_CRefs;
  6116. PerfDbgLog1(tagCINet, this, "-CINet::CPrivUnknown::AddRef (cRefs:%ld)", lRet);
  6117. DEBUG_LEAVE(lRet);
  6118. return lRet;
  6119. }
  6120. //+---------------------------------------------------------------------------
  6121. //
  6122. // Function: CINet::Release
  6123. //
  6124. // Synopsis:
  6125. //
  6126. // Arguments: [ULONG] --
  6127. //
  6128. // Returns:
  6129. //
  6130. // History: 10-29-1996 JohannP (Johann Posch) Created
  6131. //
  6132. // Notes:
  6133. //
  6134. //----------------------------------------------------------------------------
  6135. STDMETHODIMP_(ULONG) CINet::CPrivUnknown::Release(void)
  6136. {
  6137. DEBUG_ENTER((DBG_APP,
  6138. Dword,
  6139. "CINet::CPrivUnknown::IUnknown::Release",
  6140. "this=%#x",
  6141. this
  6142. ));
  6143. PerfDbgLog(tagCINet, this, "+CINet::CPrivUnknown::Release");
  6144. CINet *pCINet = GETPPARENT(this, CINet, _Unknown);
  6145. LONG lRet = --_CRefs;
  6146. if (lRet == 0)
  6147. {
  6148. delete pCINet;
  6149. }
  6150. PerfDbgLog1(tagCINet, this, "-CINet::CPrivUnknown::Release (cRefs:%ld)", lRet);
  6151. DEBUG_LEAVE(lRet);
  6152. return lRet;
  6153. }
  6154. //+---------------------------------------------------------------------------
  6155. //
  6156. // Method: CINet::OnINetReadDirect
  6157. //
  6158. // Synopsis:
  6159. //
  6160. // Arguments: [dwResult] --
  6161. //
  6162. // Returns:
  6163. //
  6164. // History: 4-28-1997 JohannP (Johann Posch) Created
  6165. //
  6166. // Notes:
  6167. //
  6168. //----------------------------------------------------------------------------
  6169. HRESULT CINet::OnINetReadDirect(DWORD dwResult)
  6170. {
  6171. DEBUG_ENTER((DBG_APP,
  6172. Hresult,
  6173. "CINet::OnINetReadDirect",
  6174. "this=%#x, %#x",
  6175. this, dwResult
  6176. ));
  6177. PerfDbgLog(tagCINet, this, "+CINet::OnINetReadDirect");
  6178. HRESULT hr = NOERROR;
  6179. PProtAssert((GetStatePending() == E_PENDING));
  6180. // set state to normal - no pending transaction
  6181. SetStatePending(NOERROR);
  6182. if (OperationOnAparmentThread(INetState_SEND_REQUEST))
  6183. {
  6184. TransitState(INetState_READ_DIRECT);
  6185. }
  6186. else
  6187. {
  6188. hr = INetReadDirect();
  6189. }
  6190. PerfDbgLog1(tagCINet, this, "-CINet::OnINetReadDirect (hr:%lx)", hr);
  6191. DEBUG_LEAVE(hr);
  6192. return hr;
  6193. }
  6194. //+---------------------------------------------------------------------------
  6195. //
  6196. // Method: CINet::INetReadDirect
  6197. //
  6198. // Synopsis:
  6199. //
  6200. // Arguments: (none)
  6201. //
  6202. // Returns:
  6203. //
  6204. // History: 4-28-1997 JohannP (Johann Posch) Created
  6205. //
  6206. // Notes:
  6207. //
  6208. //----------------------------------------------------------------------------
  6209. HRESULT CINet::INetReadDirect()
  6210. {
  6211. DEBUG_ENTER((DBG_APP,
  6212. Hresult,
  6213. "CINet::INetReadDirect",
  6214. "this=%#x",
  6215. this
  6216. ));
  6217. PerfDbgLog(tagCINet, this, "+CINet::INetReadDirect");
  6218. HRESULT hr = NOERROR;
  6219. DWORD dwError;
  6220. ULONG cbBytesAvailable = 1;
  6221. ULONG cbBytesReport = 0;
  6222. SetINetState(INetState_READ_DIRECT);
  6223. //BUGBUG: we hit this assertion sometimes.
  6224. //PProtAssert((GetStatePending() == NOERROR));
  6225. _hrError = INET_E_OK;
  6226. if (!_fFilenameReported)
  6227. {
  6228. char szFilename[MAX_PATH];
  6229. HRESULT hr1 = GetUrlCacheFilename(szFilename, MAX_PATH);
  6230. if (hr1 == NOERROR && szFilename[0] != '\0')
  6231. {
  6232. ReportNotification(BINDSTATUS_CACHEFILENAMEAVAILABLE, (LPSTR) szFilename);
  6233. _fFilenameReported = TRUE;
  6234. }
  6235. }
  6236. if ((GetStatePending() == E_PENDING))
  6237. {
  6238. // nothing to do - data for this notfication
  6239. // already received
  6240. DbgLog(tagCINetErr, this, "CINet::INetReadDirect E_PENIDNG");
  6241. }
  6242. else
  6243. {
  6244. if ( _fDone
  6245. || ( _cbTotalBytesRead
  6246. && _cbDataSize
  6247. && (_cbTotalBytesRead == _cbDataSize)))
  6248. {
  6249. _hrError = INET_E_DONE;
  6250. _pEmbdFilter->ReportData(_bscf, cbBytesAvailable, _cbDataSize);
  6251. ReportResultAndStop(NOERROR, _cbTotalBytesRead, _cbDataSize);
  6252. hr = NOERROR;
  6253. }
  6254. else
  6255. {
  6256. if (_bscf & BSCF_DATAFULLYAVAILABLE)
  6257. {
  6258. _bscf |= BSCF_LASTDATANOTIFICATION;
  6259. _bscf &= ~BSCF_FIRSTDATANOTIFICATION;
  6260. cbBytesReport = cbBytesAvailable + _cbTotalBytesRead;
  6261. if (IsEmbdFilterOk() )
  6262. {
  6263. _pEmbdFilter->ReportData(_bscf, cbBytesReport, _cbDataSize);
  6264. }
  6265. ReportResultAndStop(NOERROR, cbBytesReport, _cbDataSize);
  6266. }
  6267. else
  6268. {
  6269. _bscf |= BSCF_AVAILABLEDATASIZEUNKNOWN;
  6270. cbBytesReport = cbBytesAvailable + _cbTotalBytesRead;
  6271. if (_pCTrans && IsEmbdFilterOk() )
  6272. {
  6273. _cbSizeLastReportData = cbBytesReport;
  6274. hr = _pEmbdFilter->ReportData(_bscf, cbBytesReport, _cbDataSize);
  6275. }
  6276. }
  6277. if (_bscf & BSCF_FIRSTDATANOTIFICATION)
  6278. {
  6279. _bscf &= ~BSCF_FIRSTDATANOTIFICATION;
  6280. _bscf |= BSCF_INTERMEDIATEDATANOTIFICATION;
  6281. }
  6282. }
  6283. }
  6284. PerfDbgLog2(tagCINet, this, "-CINet::INetReadDirect (_hrError:%lx, hr:%lx)", _hrError, hr);
  6285. DEBUG_LEAVE(hr);
  6286. return hr;
  6287. }
  6288. //+---------------------------------------------------------------------------
  6289. //
  6290. // Method: CINet::ReadDirect
  6291. //
  6292. // Synopsis:
  6293. //
  6294. // Arguments: [pBuffer] --
  6295. // [cbBytes] --
  6296. // [pcbBytes] --
  6297. //
  6298. // Returns:
  6299. //
  6300. // History: 4-28-1997 JohannP (Johann Posch) Created
  6301. //
  6302. // Notes:
  6303. //
  6304. //----------------------------------------------------------------------------
  6305. HRESULT CINet::ReadDirect(BYTE *pBuffer, DWORD cbBytes, DWORD *pcbBytes)
  6306. {
  6307. DEBUG_ENTER((DBG_APP,
  6308. Hresult,
  6309. "CINet::ReadDirect",
  6310. "this=%#x, %#x, %#x, %#x",
  6311. this, pBuffer, cbBytes, pcbBytes
  6312. ));
  6313. PerfDbgLog(tagCINet, this, "+CINet::ReadDirect");
  6314. HRESULT hr = NOERROR;
  6315. DWORD dwError;
  6316. *pcbBytes = 0;
  6317. ULONG dwReturned = 0;
  6318. //BUGBUG: turn this assertion on again
  6319. //PProtAssert((GetStatePending() == NOERROR));
  6320. if (_hrError == INET_E_DONE)
  6321. {
  6322. // means end of file
  6323. hr = S_FALSE;
  6324. }
  6325. else if (GetStatePending() != NOERROR)
  6326. {
  6327. hr = E_PENDING;
  6328. }
  6329. else
  6330. {
  6331. _hrError = INET_E_OK;
  6332. PProtAssert(((pBuffer != NULL) && (cbBytes > 0)));
  6333. //PerfDbgLog1(tagCINet, this, "CINet::ReadDirect -> InternetReadFile (dwBytesLeft:%ld)", dwBytesLeft);
  6334. LPINTERNET_BUFFERSA pIB = &_inetBufferSend;
  6335. pIB->dwStructSize = sizeof (INTERNET_BUFFERSA);
  6336. pIB->Next = 0;
  6337. pIB->lpcszHeader = 0;
  6338. pIB->dwHeadersLength = 0;
  6339. pIB->dwHeadersTotal = 0;
  6340. pIB->lpvBuffer = pBuffer;
  6341. pIB->dwBufferLength = cbBytes;
  6342. pIB->dwBufferTotal = 0;
  6343. pIB->dwOffsetLow = 0;
  6344. pIB->dwOffsetHigh = 0;
  6345. dwReturned = 0;
  6346. PProtAssert((GetStatePending() == NOERROR));
  6347. SetStatePending(E_PENDING);
  6348. if (!InternetReadFileExA(
  6349. _hRequest //IN HINTERNET hFile,
  6350. ,pIB // OUT LPINTERNET_BUFFERSA lpBuffersOut,
  6351. ,IRF_NO_WAIT // IN DWORD dwFlags,
  6352. ,0 // IN DWORD dwContext
  6353. ))
  6354. {
  6355. //
  6356. // async completion
  6357. //
  6358. dwError = GetLastError();
  6359. if (dwError != ERROR_IO_PENDING)
  6360. {
  6361. hr = _hrError = INET_E_DOWNLOAD_FAILURE;
  6362. DbgLog3(tagCINetErr, this, "CINet::ReadDirect failed: (dwError:%lx, hr:%lx, hrError:%lx)",
  6363. dwError, hr, _hrError);
  6364. }
  6365. else
  6366. {
  6367. hr = E_PENDING;
  6368. }
  6369. }
  6370. else
  6371. {
  6372. //
  6373. // sync completion
  6374. //
  6375. SetStatePending(NOERROR);
  6376. //
  6377. dwReturned = pIB->dwBufferLength;
  6378. _cbTotalBytesRead += dwReturned;
  6379. *pcbBytes = dwReturned;
  6380. PerfDbgLog3(tagCINet, this, "CINet::ReadDirect == InternetReadFileEx ==> (cbBytes:%ld, dwReturned:%ld,_cbTotalBytesRead:%ld)",
  6381. cbBytes, dwReturned,_cbTotalBytesRead);
  6382. if (dwReturned == 0)
  6383. {
  6384. // eof
  6385. hr = _hrError = INET_E_DONE;
  6386. //TransDebugOut((DEB_TRACE, "%p _IN CINetStream::INetSeek\n", this));
  6387. PProtAssert(( ( (_cbDataSize && (_cbDataSize == _cbTotalBytesRead))
  6388. || (!_cbDataSize)) && "WinInet returned incorrent amount of data!!" ));
  6389. }
  6390. else
  6391. {
  6392. hr = NOERROR;
  6393. }
  6394. } // read case - bits available
  6395. *pcbBytes = dwReturned;
  6396. if (hr == INET_E_DONE)
  6397. {
  6398. hr = (dwReturned) ? S_OK : S_FALSE;
  6399. }
  6400. }
  6401. // Note: stop the download in case of DONE or ERROR!
  6402. if (_hrError != INET_E_OK)
  6403. {
  6404. ReportResultAndStop((hr == S_FALSE) ? NOERROR : hr);
  6405. }
  6406. PerfDbgLog4(tagCINet, this, "-CINet::ReadDirect (_hrError:%lx, [hr:%lx,cbBytesAsked:%ld,cbBytesReturned:%ld])",
  6407. _hrError, hr, cbBytes, *pcbBytes);
  6408. DEBUG_LEAVE(hr);
  6409. return hr;
  6410. }
  6411. //+---------------------------------------------------------------------------
  6412. //
  6413. // Method: CINet::GetUserAgentString
  6414. //
  6415. // Synopsis:
  6416. //
  6417. // Arguments: [pBuffer] --
  6418. // [cbBytes] --
  6419. // [pcbBytes] --
  6420. //
  6421. // Returns:
  6422. //
  6423. // History: 4-28-1997 JohannP (Johann Posch) Created
  6424. //
  6425. // Notes:
  6426. //
  6427. //----------------------------------------------------------------------------
  6428. LPSTR CINet::GetUserAgentString()
  6429. {
  6430. DEBUG_ENTER((DBG_APP,
  6431. String,
  6432. "CINet::GetUserAgentString",
  6433. "this=%#x",
  6434. this
  6435. ));
  6436. PerfDbgLog(tagCINet, this, "+CINet::GetUserAgentString");
  6437. HRESULT hr = NOERROR;
  6438. ULONG ulCount = 0;
  6439. LPWSTR pwzStr = 0;
  6440. LPSTR pszStr = 0;
  6441. hr = _pOIBindInfo->GetBindString(BINDSTRING_USER_AGENT, (LPWSTR *)&pwzStr, 1, &ulCount);
  6442. if ((hr == NOERROR) && ulCount)
  6443. {
  6444. PProtAssert((pwzStr));
  6445. delete _pszUserAgentStr;
  6446. pszStr = _pszUserAgentStr = DupW2A(pwzStr);
  6447. }
  6448. else
  6449. {
  6450. pszStr = (LPSTR)::GetUserAgentString();
  6451. }
  6452. PerfDbgLog1(tagCINet, this, "-CINet::GetUserAgentString (pszStr:%s)", pszStr);
  6453. DEBUG_LEAVE(pszStr);
  6454. return pszStr;
  6455. }
  6456. BOOL GlobalUTF8Enabled()
  6457. {
  6458. DEBUG_ENTER((DBG_APP,
  6459. Bool,
  6460. "GlobalUTF8Enabled",
  6461. NULL
  6462. ));
  6463. // read the IE5 B2 global reg key
  6464. DWORD dwErr = ERROR_SUCCESS;
  6465. BOOL fRet = FALSE;
  6466. HKEY hKeyClient;
  6467. DWORD dwUTF8 = 0;
  6468. DWORD dwSize = sizeof(DWORD);
  6469. DWORD dwType;
  6470. dwErr = RegOpenKeyEx(
  6471. HKEY_CURRENT_USER,
  6472. INTERNET_POLICIES_KEY,
  6473. 0,
  6474. KEY_QUERY_VALUE,
  6475. &hKeyClient
  6476. );
  6477. if( dwErr == ERROR_SUCCESS )
  6478. {
  6479. dwErr = RegQueryValueEx(
  6480. hKeyClient,
  6481. "EnableUTF8",
  6482. 0,
  6483. &dwType,
  6484. (LPBYTE)&dwUTF8,
  6485. &dwSize
  6486. );
  6487. if( dwErr == ERROR_SUCCESS && dwUTF8 )
  6488. {
  6489. fRet = TRUE;
  6490. }
  6491. RegCloseKey(hKeyClient);
  6492. }
  6493. DEBUG_LEAVE(fRet);
  6494. return fRet;
  6495. }
  6496. // Enabled by adding a DWORD value "MBCSServername" with non=zero value under POLICY key
  6497. BOOL GlobalUTF8hackEnabled()
  6498. {
  6499. DEBUG_ENTER((DBG_APP,
  6500. Bool,
  6501. "GlobalUTF8hackEnabled",
  6502. NULL
  6503. ));
  6504. DWORD dwErr = ERROR_SUCCESS;
  6505. BOOL fRet = TRUE;
  6506. HKEY hKeyClient;
  6507. DWORD dwUTF8 = 0;
  6508. DWORD dwSize = sizeof(DWORD);
  6509. DWORD dwType;
  6510. dwErr = RegOpenKeyEx(
  6511. HKEY_CURRENT_USER,
  6512. INTERNET_POLICIES_KEY,
  6513. 0,
  6514. KEY_QUERY_VALUE,
  6515. &hKeyClient
  6516. );
  6517. if( dwErr == ERROR_SUCCESS )
  6518. {
  6519. dwErr = RegQueryValueEx(
  6520. hKeyClient,
  6521. "MBCSServername",
  6522. 0,
  6523. &dwType,
  6524. (LPBYTE)&dwUTF8,
  6525. &dwSize
  6526. );
  6527. if( dwErr == ERROR_SUCCESS && !dwUTF8 )
  6528. {
  6529. fRet = FALSE;
  6530. }
  6531. RegCloseKey(hKeyClient);
  6532. }
  6533. DEBUG_LEAVE(fRet);
  6534. return fRet;
  6535. }