Source code of Windows XP (NT5)
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.

3583 lines
119 KiB

  1. #include "priv.h"
  2. #include "iehelpid.h"
  3. #include "bindcb.h"
  4. #include "winlist.h"
  5. #include "droptgt.h"
  6. #include <mshtml.h> // CLSID_HTMLDocument
  7. #include "resource.h"
  8. #include <htmlhelp.h>
  9. #include <prsht.h>
  10. #include <inetcpl.h>
  11. #include <optary.h>
  12. #include "shdocfl.h"
  13. #include "interned.h" // IHTMLPrivateWindow
  14. #ifdef FEATURE_PICS
  15. #include <shlwapi.h>
  16. #include <ratings.h>
  17. #endif
  18. #include "dochost.h"
  19. #include <mluisupp.h>
  20. #define THISCLASS CDocObjectHost
  21. #define SUPERCLASS CDocHostUIHandler
  22. #define BSCMSG(psz, i, j) TraceMsg(TF_SHDBINDING, "shd TR-BSC::%s %x %x", psz, i, j)
  23. #define BSCMSG3(psz, i, j, k) TraceMsg(0, "shd TR-BSC::%s %x %x %x", psz, i, j, k)
  24. #define BSCMSG4(psz, i, j, k, l) TraceMsg(0, "shd TR-BSC::%s %x %x %x %x", psz, i, j, k, l)
  25. #define BSCMSGS(psz, sz) TraceMsg(0, "shd TR-BSC::%s %s", psz, sz)
  26. #define CHAINMSG(psz, x) TraceMsg(0, "shd CHAIN::%s %x", psz, x)
  27. #define PERFMSG(psz, x) TraceMsg(TF_SHDPERF, "PERF::%s %d msec", psz, x)
  28. #define OPENMSG(psz) TraceMsg(TF_SHDBINDING, "shd OPENING %s", psz)
  29. #define DM_DOCCP 0
  30. #define DM_DEBUGTFRAME 0
  31. #define DM_SELFASC TF_SHDBINDING
  32. #define DM_SSL 0
  33. #define DM_PICS 0
  34. #define DO_SEARCH_ON_STATUSCODE(x) ((x == 0) || (x == HTTP_STATUS_BAD_GATEWAY) || (x == HTTP_STATUS_GATEWAY_TIMEOUT))
  35. const static c_aidRes[] = {
  36. IDI_STATE_NORMAL, // 0
  37. IDI_STATE_FINDINGRESOURCE, // BINDSTATUS_FINDINGRESOURCE
  38. IDI_STATE_FINDINGRESOURCE, // BINDSTATUS_CONNECTING
  39. IDI_STATE_FINDINGRESOURCE, // BINDSTATUS_REDIRECTING
  40. IDI_STATE_DOWNLOADINGDATA, // BINDSTATUS_BEGINDOWNLOADDATA
  41. IDI_STATE_DOWNLOADINGDATA, // BINDSTATUS_DOWNLOADINGDATA
  42. IDI_STATE_DOWNLOADINGDATA, // BINDSTATUS_ENDDOWNLOADDATA
  43. IDI_STATE_DOWNLOADINGDATA, // BINDSTATUS_BEGINDOWNLOADCOMPONENTS
  44. IDI_STATE_DOWNLOADINGDATA, // BINDSTATUS_INSTALLINGCOMPONENTS
  45. IDI_STATE_DOWNLOADINGDATA, // BINDSTATUS_ENDDOWNLOADCOMPONENTS
  46. IDI_STATE_SENDINGREQUEST, // BINDSTATUS_USINGCACHEDCOPY
  47. IDI_STATE_SENDINGREQUEST, // BINDSTATUS_SENDINGREQUEST
  48. IDI_STATE_DOWNLOADINGDATA, // BINDSTATUS_CLASSIDAVAILABLE
  49. };
  50. extern HICON g_ahiconState[IDI_STATE_LAST-IDI_STATE_FIRST+1];
  51. #define SEARCHPREFIX L"? "
  52. #define SEARCHPREFIXSIZE sizeof(SEARCHPREFIX)
  53. #define SEARCHPREFIXLENGTH 2
  54. // Put the most common errors first in c_aErrorUrls.
  55. //
  56. //========================================================
  57. //
  58. // WARNING - Thinking of changing the Table ?
  59. //
  60. // You also need to update the IsErrorHandled in mshtml
  61. // src\site\download\dwnbind.cxx
  62. //
  63. //========================================================
  64. ErrorUrls c_aErrorUrls[] =
  65. {
  66. {404, TEXT("http_404.htm")},
  67. {ERRORPAGE_DNS, TEXT("dnserror.htm")},
  68. {ERRORPAGE_NAVCANCEL, TEXT("navcancl.htm")},
  69. {ERRORPAGE_SYNTAX, TEXT("syntax.htm")},
  70. {400, TEXT("http_400.htm")},
  71. {403, TEXT("http_403.htm")},
  72. {405, TEXT("http_gen.htm")},
  73. {406, TEXT("http_406.htm")},
  74. {408, TEXT("servbusy.htm")},
  75. {409, TEXT("servbusy.htm")},
  76. {410, TEXT("http_410.htm")},
  77. {500, TEXT("http_500.htm")},
  78. {501, TEXT("http_501.htm")},
  79. {505, TEXT("http_501.htm")},
  80. {ERRORPAGE_OFFCANCEL, TEXT("offcancl.htm")},
  81. {ERRORPAGE_CHANNELNOTINCACHE, TEXT("cacheerr.htm")},
  82. };
  83. //
  84. // Determine if there is an internal error page for the given http error.
  85. //
  86. BOOL IsErrorHandled(DWORD dwError)
  87. {
  88. BOOL fRet = FALSE;
  89. for (int i = 0; i < ARRAYSIZE(c_aErrorUrls); i++)
  90. {
  91. if (dwError == c_aErrorUrls[i].dwError)
  92. {
  93. fRet = TRUE;
  94. break;
  95. }
  96. }
  97. return fRet;
  98. }
  99. const SA_BSTRGUID s_sstrSearchIndex = {
  100. 38 * SIZEOF(WCHAR),
  101. L"{265b75c0-4158-11d0-90f6-00c04fd497ea}"
  102. };
  103. //extern const SA_BSTRGUID s_sstrSearchFlags;
  104. const SA_BSTRGUID s_sstrSearchFlags = {
  105. 38 * SIZEOF(WCHAR),
  106. L"{265b75c1-4158-11d0-90f6-00c04fd497ea}"
  107. };
  108. EXTERN_C const SA_BSTRGUID s_sstrSearch = {
  109. 38 * SIZEOF(WCHAR),
  110. L"{118D6040-8494-11d2-BBFE-0060977B464C}"
  111. };
  112. EXTERN_C const SA_BSTRGUID s_sstrFailureUrl = {
  113. 38 * SIZEOF(WCHAR),
  114. L"{04AED800-8494-11d2-BBFE-0060977B464C}"
  115. };
  116. //
  117. // Clears that parameters set by window.external.AutoScan()
  118. //
  119. HRESULT _ClearSearchString(IServiceProvider* psp)
  120. {
  121. HRESULT hr = E_FAIL;
  122. if (psp == NULL)
  123. return hr;
  124. IWebBrowser2 *pWB2 = NULL;
  125. hr = psp->QueryService(SID_SHlinkFrame, IID_IWebBrowser2, (LPVOID*)&pWB2);
  126. if (pWB2 && SUCCEEDED(hr))
  127. {
  128. VARIANT v;
  129. VariantInit(&v);
  130. v.vt = VT_EMPTY;
  131. hr = pWB2->PutProperty((BSTR)s_sstrSearch.wsz, v);
  132. hr = pWB2->PutProperty((BSTR)s_sstrFailureUrl.wsz, v);
  133. pWB2->Release();
  134. }
  135. return hr;
  136. }
  137. //
  138. // Gets the string that was entered in the addressbar
  139. //
  140. HRESULT _GetSearchString(IServiceProvider* psp, VARIANT* pvarSearch)
  141. {
  142. HRESULT hr = E_FAIL;
  143. if (psp != NULL)
  144. {
  145. VariantInit(pvarSearch);
  146. IDockingWindow* psct = NULL;
  147. IOleCommandTarget* poct;
  148. // first see if there is an ISearchContext to get this information from
  149. ISearchContext * pSC = NULL;
  150. hr = psp->QueryService(SID_STopWindow, IID_ISearchContext, (void **) &pSC);
  151. if (SUCCEEDED(hr))
  152. {
  153. RIP(pSC != NULL);
  154. pvarSearch->vt = VT_BSTR;
  155. hr = pSC->GetSearchText(&(pvarSearch->bstrVal));
  156. pSC->Release();
  157. }
  158. else
  159. {
  160. // otherwise try to get the search string directly out of the address bar
  161. hr = psp->QueryService(SID_SExplorerToolbar, IID_IDockingWindow, (LPVOID*)&psct);
  162. if (SUCCEEDED(hr))
  163. {
  164. hr = psct->QueryInterface(IID_IOleCommandTarget, (LPVOID *)&poct);
  165. if (SUCCEEDED(hr))
  166. {
  167. // NULL is the first parameter so our ErrorMsgBox
  168. // doesn't call EnableModelessSB()
  169. // If we don't, our pdoh members may be freed
  170. // by the time we return.
  171. hr = poct->Exec(&CGID_Explorer, SBCMDID_GETUSERADDRESSBARTEXT, 0, NULL, pvarSearch);
  172. poct->Release();
  173. }
  174. psct->Release();
  175. }
  176. }
  177. }
  178. return hr;
  179. }
  180. //
  181. // Get page that should be displayed if the AutoScan fails
  182. //
  183. HRESULT _GetScanFailureUrl(IServiceProvider* psp, VARIANT* pvarFailureUrl)
  184. {
  185. HRESULT hr = E_FAIL;
  186. if (psp == NULL)
  187. return hr;
  188. //
  189. // See if a default failure page is stored as a property of the page
  190. //
  191. IWebBrowser2 *pWB2 = NULL;
  192. hr = psp->QueryService(SID_SHlinkFrame, IID_IWebBrowser2, (LPVOID*)&pWB2);
  193. if (pWB2 && SUCCEEDED(hr))
  194. {
  195. hr = pWB2->GetProperty((BSTR)s_sstrFailureUrl.wsz, pvarFailureUrl);
  196. pWB2->Release();
  197. }
  198. return hr;
  199. }
  200. HRESULT _GetSearchInfo(IServiceProvider *psp, LPDWORD pdwIndex, LPBOOL pfAllowSearch, LPBOOL pfContinueSearch, LPBOOL pfSentToEngine, VARIANT* pvarUrl)
  201. {
  202. HRESULT hr = E_FAIL;
  203. DWORD dwFlags = 0;
  204. if (psp) {
  205. IWebBrowser2 *pWB2 = NULL;
  206. hr = psp->QueryService(SID_SHlinkFrame, IID_IWebBrowser2, (LPVOID*)&pWB2);
  207. if (pWB2 && SUCCEEDED(hr)) {
  208. if (pdwIndex) {
  209. VARIANT v;
  210. if (SUCCEEDED(pWB2->GetProperty((BSTR)s_sstrSearchIndex.wsz, &v))) {
  211. if (v.vt == VT_I4)
  212. *pdwIndex = v.lVal;
  213. VariantClear(&v);
  214. }
  215. }
  216. if (pfAllowSearch || pfContinueSearch || pfSentToEngine) {
  217. VARIANT v;
  218. if (SUCCEEDED(pWB2->GetProperty((BSTR)s_sstrSearchFlags.wsz, &v))) {
  219. if (v.vt == VT_I4)
  220. dwFlags = v.lVal;
  221. VariantClear(&v);
  222. }
  223. }
  224. //
  225. // If we have a search string property, and the index is zero, we start
  226. // with the second autoscan index. This is because the first index should
  227. // have already been tried (see window.external.AutoScan()).
  228. //
  229. if (pvarUrl)
  230. {
  231. VariantInit(pvarUrl); // in case of failure
  232. if (SUCCEEDED(pWB2->GetProperty((BSTR)s_sstrSearch.wsz, pvarUrl)) &&
  233. pvarUrl->vt == VT_BSTR && pdwIndex && *pdwIndex == 0)
  234. {
  235. *pdwIndex = 2;
  236. }
  237. }
  238. if (pfAllowSearch)
  239. *pfAllowSearch = ((dwFlags & 0x01) ? TRUE : FALSE);
  240. if (pfContinueSearch)
  241. *pfContinueSearch = ((dwFlags & 0x02) ? TRUE : FALSE);
  242. if (pfSentToEngine)
  243. *pfSentToEngine = ((dwFlags & 0x04) ? TRUE : FALSE);
  244. pWB2->Release();
  245. }
  246. }
  247. return hr;
  248. }
  249. HRESULT CDocObjectHost::CDOHBindStatusCallback::_SetSearchInfo(CDocObjectHost *pdoh, DWORD dwIndex, BOOL fAllowSearch, BOOL fContinueSearch, BOOL fSentToEngine)
  250. {
  251. HRESULT hr = E_FAIL;
  252. DWORD dwFlags = 0;
  253. dwFlags = (fAllowSearch ? 0x01 : 0) +
  254. (fContinueSearch ? 0x02 : 0) +
  255. (fSentToEngine ? 0x04 : 0);
  256. if (pdoh->_psp)
  257. {
  258. IWebBrowser2 *pWB2 = NULL;
  259. hr = pdoh->_psp->QueryService(SID_SHlinkFrame, IID_IWebBrowser2, (LPVOID*)&pWB2);
  260. if (pWB2 && SUCCEEDED(hr))
  261. {
  262. VARIANT v;
  263. VariantInit (&v);
  264. v.vt = VT_I4;
  265. v.lVal = dwIndex;
  266. pWB2->PutProperty((BSTR)s_sstrSearchIndex.wsz, v);
  267. v.vt = VT_I4;
  268. v.lVal = dwFlags;
  269. pWB2->PutProperty((BSTR)s_sstrSearchFlags.wsz, v);
  270. pWB2->Release();
  271. }
  272. }
  273. // If we are done, clear any parameters set by window.external.AutoScan().
  274. if (!fContinueSearch)
  275. {
  276. _ClearSearchString(pdoh->_psp);
  277. }
  278. TraceMsg(TF_SHDNAVIGATE, "::HFNS_SetSearchInfo() hr = %X, index = %d, allow = %d, cont = %d, sent = %d", hr, dwIndex, fAllowSearch, fContinueSearch, fSentToEngine);
  279. return hr;
  280. }
  281. //
  282. // Gets the prefix/postfix to use for autoscanning (www.%s.com, etc)
  283. //
  284. LONG GetSearchFormatString(DWORD dwIndex, LPTSTR psz, DWORD cbpsz)
  285. {
  286. TCHAR szValue[10];
  287. DWORD dwType;
  288. wnsprintf(szValue, ARRAYSIZE(szValue), TEXT("%d"), dwIndex);
  289. return SHRegGetUSValue(REGSTR_PATH_SEARCHSTRINGS, szValue, &dwType, (LPVOID)psz, &cbpsz, FALSE, NULL, 0);
  290. }
  291. // dwSearchForExtensions : 0 do not search
  292. // dwSearchForExtensions : 1 search through list of exts.
  293. // dwSearchForExtensions : 2 move on to autosearch
  294. // 0 = never ask, never search
  295. // 1 = always ask
  296. // 2 = never ask, always search
  297. HRESULT GetSearchKeys(IServiceProvider * psp, LPDWORD pdwSearchStyle, LPDWORD pdwSearchForExtensions, LPDWORD pdwDo404Search)
  298. {
  299. RIP(pdwSearchStyle != NULL);
  300. RIP(pdwSearchForExtensions != NULL);
  301. RIP(pdwDo404Search != NULL);
  302. GetSearchStyle(psp, pdwSearchStyle);
  303. if (*pdwSearchStyle == 0)
  304. {
  305. *pdwSearchForExtensions = NO_SUFFIXES;
  306. *pdwDo404Search = NEVERSEARCH;
  307. }
  308. else
  309. {
  310. *pdwSearchForExtensions = SCAN_SUFFIXES;
  311. *pdwDo404Search = ALWAYSSEARCH;
  312. }
  313. return S_OK;
  314. } // GetSearchKeys
  315. //
  316. // Map error codes to error urls.
  317. //
  318. int EUIndexFromError(DWORD dwError)
  319. {
  320. for (int i = 0; i < ARRAYSIZE(c_aErrorUrls); i++)
  321. {
  322. if (dwError == c_aErrorUrls[i].dwError)
  323. break;
  324. }
  325. ASSERT(i < ARRAYSIZE(c_aErrorUrls));
  326. return i;
  327. }
  328. //
  329. // IsErrorUrl determines if the given url is an internal error page url.
  330. //
  331. BOOL IsErrorUrl(LPCWSTR pwszDisplayName)
  332. {
  333. BOOL fRet = FALSE;
  334. TCHAR szDisplayName[MAX_URL_STRING];
  335. UnicodeToTChar(pwszDisplayName, szDisplayName, ARRAYSIZE(szDisplayName));
  336. //
  337. // First check if the prefix matches.
  338. //
  339. if (0 == StrCmpN(szDisplayName, TEXT("res://"), 6))
  340. {
  341. int iResStart;
  342. // find the resource name part of the URL
  343. // use the fact that the DLL path will be using
  344. // '\' as delimiters while the URL in general
  345. // uses '/'
  346. iResStart = 6;
  347. while (szDisplayName[iResStart] != TEXT('/') &&
  348. szDisplayName[iResStart] != TEXT('\0'))
  349. {
  350. iResStart++;
  351. }
  352. iResStart++; // get off the '/'
  353. //
  354. // Check each url in order.
  355. //
  356. for (int i = 0; i < ARRAYSIZE(c_aErrorUrls); i++)
  357. {
  358. if (0 == StrCmpN(szDisplayName + iResStart, c_aErrorUrls[i].pszUrl,
  359. lstrlen(c_aErrorUrls[i].pszUrl)))
  360. {
  361. fRet = TRUE;
  362. break;
  363. }
  364. }
  365. }
  366. return fRet;
  367. }
  368. //
  369. // When an http error occurs the server generally returns a page. The
  370. // threshold value this function returns is used to determine if the
  371. // server page is displayed (if the size of the returned page is greater than
  372. // the threshold) or if an internal error page is shown (if the returned page
  373. // is smaller than the threshold).
  374. //
  375. DWORD _GetErrorThreshold(DWORD dwError)
  376. {
  377. DWORD dwRet;
  378. TCHAR szValue[11]; //Should be large enough to hold max dword 4294967295
  379. DWORD cbValue = ARRAYSIZE(szValue);
  380. DWORD cbdwRet = sizeof(dwRet);
  381. DWORD dwType = REG_DWORD;
  382. wnsprintf(szValue, ARRAYSIZE(szValue), TEXT("%d"), dwError);
  383. if (ERROR_SUCCESS != SHRegGetUSValue(REGSTR_PATH_THRESHOLDS, szValue,
  384. &dwType, (LPVOID)&dwRet, &cbdwRet,
  385. FALSE, NULL, 0))
  386. {
  387. dwRet = 512; // hard coded default size if all else fails.
  388. }
  389. return dwRet;
  390. }
  391. void CDocObjectHost::CDOHBindStatusCallback::_RegisterObjectParam(IBindCtx* pbc)
  392. {
  393. // pbc->RegisterObjectParam(L"BindStatusCallback", this);
  394. _fAborted = FALSE;
  395. HRESULT hres = RegisterBindStatusCallback(pbc, this, 0, 0);
  396. BSCMSG3(TEXT("_RegisterObjectParam returned"), hres, this, pbc);
  397. }
  398. void CDocObjectHost::CDOHBindStatusCallback::_RevokeObjectParam(IBindCtx* pbc)
  399. {
  400. // pbc->RevokeObjectParam(L"BindStatusCallback");
  401. HRESULT hres = RevokeBindStatusCallback(pbc, this);
  402. AssertMsg(SUCCEEDED(hres), TEXT("URLMON bug??? RevokeBindStatusCallback failed %x"), hres);
  403. BSCMSG3(TEXT("_RevokeObjectParam returned"), hres, this, pbc);
  404. }
  405. CDocObjectHost::CDOHBindStatusCallback::~CDOHBindStatusCallback()
  406. {
  407. TraceMsg(DM_DEBUGTFRAME, "dtor CDocObjectHost::CBSC %x", this);
  408. if (_pib) {
  409. AssertMsg(0, TEXT("CBSC::~ _pib is %x (this=%x)"), _pib, this);
  410. }
  411. ATOMICRELEASE(_pib);
  412. if (_pbc) {
  413. AssertMsg(0, TEXT("CBSC::~ _pbc is %x (this=%x)"), _pbc, this);
  414. }
  415. ATOMICRELEASE(_pbc);
  416. if (_psvPrev) {
  417. AssertMsg(0, TEXT("CBSC::~ _psvPrev is %x (this=%x)"), _psvPrev, this);
  418. }
  419. ATOMICRELEASE(_psvPrev);
  420. ATOMICRELEASE(_pbscChained);
  421. ATOMICRELEASE(_pnegotiateChained);
  422. if (_hszPostData)
  423. {
  424. GlobalFree(_hszPostData);
  425. _hszPostData = NULL;
  426. }
  427. if (_pszHeaders)
  428. {
  429. LocalFree(_pszHeaders);
  430. _pszHeaders = NULL;
  431. }
  432. if (_pszRedirectedURL)
  433. {
  434. LocalFree(_pszRedirectedURL);
  435. _pszRedirectedURL = NULL;
  436. }
  437. if(_pszCacheFileName)
  438. {
  439. LocalFree(_pszCacheFileName);
  440. _pszCacheFileName = NULL;
  441. }
  442. if (_pszPolicyRefURL)
  443. {
  444. LocalFree(_pszPolicyRefURL);
  445. _pszPolicyRefURL = NULL;
  446. }
  447. if (_pszP3PHeader)
  448. {
  449. LocalFree(_pszP3PHeader);
  450. _pszP3PHeader = NULL;
  451. }
  452. }
  453. HRESULT CDocObjectHost::CDOHBindStatusCallback::QueryInterface(REFIID riid, LPVOID * ppvObj)
  454. {
  455. if (IsEqualIID(riid, IID_IBindStatusCallback) ||
  456. IsEqualIID(riid, IID_IUnknown))
  457. {
  458. *ppvObj = SAFECAST(this, IBindStatusCallback*);
  459. }
  460. else if (IsEqualIID(riid, IID_IHttpNegotiate))
  461. {
  462. *ppvObj = SAFECAST(this, IHttpNegotiate*);
  463. }
  464. else if (IsEqualIID(riid, IID_IAuthenticate))
  465. {
  466. *ppvObj = SAFECAST(this, IAuthenticate*);
  467. }
  468. else if (IsEqualIID(riid, IID_IServiceProvider))
  469. {
  470. *ppvObj = SAFECAST(this, IServiceProvider*);
  471. }
  472. else if (IsEqualIID(riid, IID_IHttpSecurity))
  473. {
  474. *ppvObj = SAFECAST(this, IHttpSecurity*);
  475. }
  476. else if (IsEqualIID(riid, IID_IWindowForBindingUI))
  477. {
  478. *ppvObj = SAFECAST(this, IWindowForBindingUI*);
  479. }
  480. else
  481. {
  482. *ppvObj = NULL;
  483. return E_NOINTERFACE;
  484. }
  485. AddRef();
  486. return NOERROR;
  487. }
  488. ULONG CDocObjectHost::CDOHBindStatusCallback::AddRef(void)
  489. {
  490. CDocObjectHost* pdoh = IToClass(CDocObjectHost, _bsc, this);
  491. return pdoh->AddRef();
  492. }
  493. ULONG CDocObjectHost::CDOHBindStatusCallback::Release(void)
  494. {
  495. CDocObjectHost* pdoh = IToClass(CDocObjectHost, _bsc, this);
  496. return pdoh->Release();
  497. }
  498. void SetBindfFlagsBasedOnAmbient(BOOL fAmbientOffline, DWORD *grfBindf);
  499. #define CP_UCS_2 1200 // Unicode, ISO 10646
  500. #define CP_UCS_2_BIGENDIAN 1201 // Unicode
  501. #define CP_UTF_8 65001
  502. UINT
  503. NavigatableCodePage(UINT cp)
  504. {
  505. return (cp == CP_UCS_2 || cp == CP_UCS_2_BIGENDIAN) ? CP_UTF_8 : cp;
  506. }
  507. HRESULT CDocObjectHost::CDOHBindStatusCallback::GetBindInfo(
  508. DWORD* grfBINDF,
  509. BINDINFO *pbindinfo)
  510. {
  511. if ( !grfBINDF || !pbindinfo || !pbindinfo->cbSize )
  512. return E_INVALIDARG;
  513. DWORD dwConnectedStateFlags = 0;
  514. CDocObjectHost* pdoh = IToClass(CDocObjectHost, _bsc, this);
  515. BSCMSG(TEXT("GetBindInfo"), 0, 0);
  516. *grfBINDF = BINDF_ASYNCHRONOUS;
  517. // Delegation is valid ONLY for the ::GetBindInfo() method
  518. if (_pbscChained) {
  519. CHAINMSG("GetBindInfo", grfBINDF);
  520. _pbscChained->GetBindInfo(grfBINDF, pbindinfo);
  521. DWORD dwFlags = 0;
  522. if (pdoh->_pwb)
  523. {
  524. pdoh->_pwb->GetFlags(&dwFlags);
  525. }
  526. pbindinfo->dwCodePage = (dwFlags & BSF_SETNAVIGATABLECODEPAGE)
  527. ? NavigatableCodePage(pdoh->_uiCP)
  528. : pdoh->_uiCP;
  529. // As far as offline mode is concerned, we want the latest
  530. // info. Over-rule what the delegated IBSC returned
  531. SetBindfFlagsBasedOnAmbient(_bFrameIsOffline, grfBINDF);
  532. if(_bFrameIsSilent)
  533. *grfBINDF |= BINDF_NO_UI;
  534. else
  535. *grfBINDF &= ~BINDF_NO_UI;
  536. }
  537. else
  538. {
  539. // fill out the BINDINFO struct
  540. *grfBINDF = 0;
  541. BuildBindInfo(grfBINDF,pbindinfo,_hszPostData,_cbPostData,
  542. _bFrameIsOffline, _bFrameIsSilent, FALSE, /* bHyperlink */
  543. (IBindStatusCallback *) this);
  544. // HTTP headers are added by the callback to our
  545. // IHttpNegotiate::BeginningTransaction() method
  546. }
  547. // Remember it to perform modeless download for POST case.
  548. _dwBindVerb = pbindinfo->dwBindVerb;
  549. // Remember this to use when populating the threadparams for CDownload.
  550. // (FerhanE): We are only remembering the restricted zone enforcement
  551. // to not break anything that depended on other flags being
  552. // not set before.
  553. _dwBindf = *grfBINDF & BINDF_ENFORCERESTRICTED;
  554. return S_OK;
  555. }
  556. // *** IAuthenticate ***
  557. HRESULT CDocObjectHost::CDOHBindStatusCallback::Authenticate(
  558. HWND *phwnd,
  559. LPWSTR *pszUsername,
  560. LPWSTR *pszPassword)
  561. {
  562. CDocObjectHost* pdoh = IToClass(CDocObjectHost, _bsc, this);
  563. if (!phwnd || !pszUsername || !pszPassword)
  564. return E_POINTER;
  565. if(!_bFrameIsSilent){
  566. if (pdoh->_psb) {
  567. pdoh->_psb->GetWindow(phwnd);
  568. } else {
  569. *phwnd = pdoh->_hwnd;
  570. }
  571. }else{
  572. *phwnd = NULL;
  573. }
  574. *pszUsername = NULL;
  575. *pszPassword = NULL;
  576. // If we're a frame in the active desktop, then find out
  577. // the user name and password are stored with the subscription
  578. // and use it
  579. if(_IsDesktopItem(pdoh))
  580. {
  581. // Get the URL
  582. LPOLESTR pszURL;
  583. HRESULT hres;
  584. hres = pdoh->_GetCurrentPageW(&pszURL, TRUE);
  585. if(SUCCEEDED(hres))
  586. {
  587. IActiveDesktop *pActiveDesk;
  588. hres = CoCreateInstance(CLSID_ActiveDesktop, NULL, CLSCTX_INPROC_SERVER, IID_IActiveDesktop, (LPVOID*)&pActiveDesk);
  589. if(SUCCEEDED(hres))
  590. {
  591. // Get the subscribed URL for this
  592. COMPONENT Component;
  593. Component.dwSize = SIZEOF(Component);
  594. Component.wszSubscribedURL[0] = TEXT('\0');
  595. hres = pActiveDesk->GetDesktopItemBySource(pszURL, &Component, 0);
  596. if(SUCCEEDED(hres) && Component.wszSubscribedURL[0])
  597. {
  598. // We have a non null subscribed URL
  599. // Gotta find the user name and password
  600. // associated with this subscription
  601. ISubscriptionMgr *pSubsMgr;
  602. hres = CoCreateInstance(CLSID_SubscriptionMgr, NULL,
  603. CLSCTX_INPROC_SERVER,
  604. IID_ISubscriptionMgr, (LPVOID*)&pSubsMgr);
  605. if(SUCCEEDED(hres))
  606. {
  607. SUBSCRIPTIONINFO SubInfo;
  608. SubInfo.cbSize = sizeof(SUBSCRIPTIONINFO);
  609. SubInfo.fUpdateFlags = (SUBSINFO_NEEDPASSWORD | SUBSINFO_TYPE
  610. | SUBSINFO_USER | SUBSINFO_PASSWORD);
  611. SubInfo.bstrUserName = NULL;
  612. SubInfo.bstrPassword = NULL;
  613. hres = pSubsMgr->GetSubscriptionInfo(Component.wszSubscribedURL, &SubInfo);
  614. if(SUCCEEDED(hres) && SubInfo.bNeedPassword)
  615. {
  616. if((SubInfo.bstrUserName) && (SubInfo.bstrPassword))
  617. {
  618. // Copy user name and password
  619. SHStrDupW(SubInfo.bstrPassword, pszPassword);
  620. SHStrDupW(SubInfo.bstrUserName, pszUsername);
  621. }
  622. }
  623. if(SubInfo.bstrPassword)
  624. SysFreeString(SubInfo.bstrPassword);
  625. if(SubInfo.bstrUserName)
  626. SysFreeString(SubInfo.bstrUserName);
  627. pSubsMgr->Release();
  628. }
  629. }
  630. pActiveDesk->Release();
  631. }
  632. OleFree(pszURL);
  633. }
  634. }
  635. return S_OK;
  636. }
  637. // *** IServiceProvider ***
  638. HRESULT CDocObjectHost::CDOHBindStatusCallback::QueryService(REFGUID guidService,
  639. REFIID riid, void **ppvObj)
  640. {
  641. HRESULT hres = E_FAIL;
  642. *ppvObj = NULL;
  643. if (IsEqualGUID(guidService, IID_IAuthenticate)) {
  644. return QueryInterface(riid, ppvObj);
  645. }
  646. else if (IsEqualGUID(guidService, IID_ITargetFrame2))
  647. {
  648. return IToClass(CDocObjectHost, _bsc, this)->QueryService(
  649. guidService,
  650. riid,
  651. ppvObj);
  652. }
  653. else if (_pbscChained)
  654. {
  655. // Has a delegating IBindStatusCallback.
  656. IServiceProvider* psp;
  657. hres = _pbscChained->QueryInterface(IID_IServiceProvider, (LPVOID*)&psp);
  658. if (SUCCEEDED(hres)) {
  659. // It supports ServiceProvider, just delegate.
  660. hres = psp->QueryService(guidService, riid, ppvObj);
  661. psp->Release();
  662. } else if (IsEqualGUID(guidService, riid)) {
  663. // It does not supports ServiceProvide, try QI.
  664. hres = _pbscChained->QueryInterface(riid, ppvObj);
  665. }
  666. }
  667. return hres;
  668. }
  669. HRESULT CDocObjectHost::CDOHBindStatusCallback::OnStartBinding(
  670. DWORD grfBSCOption, IBinding *pib)
  671. {
  672. BSCMSG(TEXT("OnStartBinding"), _pib, pib);
  673. CDocObjectHost* pdoh = IToClass(CDocObjectHost, _bsc, this);
  674. _fBinding = TRUE;
  675. _fDocWriteAbort = FALSE;
  676. _fBoundToMSHTML = FALSE;
  677. ASSERT(pdoh->_pocthf);
  678. // ASSERT(_pib==NULL);
  679. ATOMICRELEASE(_pib);
  680. _pib = pib;
  681. if (_pib) {
  682. _pib->AddRef();
  683. }
  684. #ifndef NO_DELEGATION
  685. if (_pbscChained) {
  686. CHAINMSG("OnStartBinding", grfBSCOption);
  687. _pbscChained->OnStartBinding(grfBSCOption, pib);
  688. }
  689. #endif
  690. pdoh->_fShowProgressCtl = TRUE;
  691. pdoh->_PlaceProgressBar(TRUE);
  692. _privacyQueue.Reset();
  693. ResetPrivacyInfo();
  694. return S_OK;
  695. }
  696. HRESULT CDocObjectHost::CDOHBindStatusCallback::GetPriority(LONG *pnPriority)
  697. {
  698. BSCMSG(TEXT("GetPriority"), 0, 0);
  699. *pnPriority = NORMAL_PRIORITY_CLASS;
  700. #ifndef NO_DELEGATION
  701. if (_pbscChained) {
  702. _pbscChained->GetPriority(pnPriority);
  703. }
  704. #endif
  705. return S_OK;
  706. }
  707. void CDocObjectHost::CDOHBindStatusCallback::ResetPrivacyInfo()
  708. {
  709. _dwPrivacyFlags = 0;
  710. if (_pszPolicyRefURL)
  711. {
  712. LocalFree(_pszPolicyRefURL);
  713. _pszPolicyRefURL = NULL;
  714. }
  715. if (_pszP3PHeader)
  716. {
  717. LocalFree(_pszP3PHeader);
  718. _pszP3PHeader = NULL;
  719. }
  720. }
  721. HRESULT CDocObjectHost::CDOHBindStatusCallback::AddToPrivacyQueue(LPTSTR * ppszUrl,
  722. LPTSTR * ppszPolicyRef,
  723. LPTSTR * ppszP3PHeader,
  724. DWORD dwFlags)
  725. {
  726. CPrivacyRecord *pRecord = new CPrivacyRecord;
  727. if (!pRecord)
  728. {
  729. return E_OUTOFMEMORY;
  730. }
  731. HRESULT hRes = S_OK;
  732. hRes = pRecord->Init(ppszUrl, ppszPolicyRef, ppszP3PHeader, dwFlags);
  733. if (SUCCEEDED(hRes))
  734. _privacyQueue.Queue(pRecord);
  735. else
  736. delete pRecord;
  737. return hRes;
  738. }
  739. HRESULT CDocObjectHost::CDOHBindStatusCallback::BuildRecord()
  740. {
  741. HRESULT hRes = S_OK;
  742. CDocObjectHost* pdoh = NULL;
  743. TCHAR * pszUrl = NULL;
  744. if (_pszRedirectedURL)
  745. {
  746. hRes = AddToPrivacyQueue(&_pszRedirectedURL, &_pszPolicyRefURL, &_pszP3PHeader, _dwPrivacyFlags);
  747. goto cleanup;
  748. }
  749. pdoh = IToClass(CDocObjectHost, _bsc, this);
  750. // Get the current URL to add
  751. pszUrl = new TCHAR[MAX_URL_STRING];
  752. if (!pszUrl)
  753. {
  754. hRes = E_OUTOFMEMORY;
  755. goto cleanup;
  756. }
  757. pszUrl[0] = TEXT('\0');
  758. if (pdoh->_pidl)
  759. {
  760. hRes = IEGetDisplayName(pdoh->_pidl, pszUrl, SHGDN_FORPARSING);
  761. }
  762. else
  763. {
  764. LPOLESTR pwUrl = NULL;
  765. hRes = pdoh->_GetCurrentPageW(&pwUrl, TRUE);
  766. if (SUCCEEDED(hRes))
  767. {
  768. StrCpyN(pszUrl, pwUrl, MAX_URL_STRING);
  769. OleFree(pwUrl);
  770. }
  771. }
  772. hRes = AddToPrivacyQueue(&pszUrl, &_pszPolicyRefURL, &_pszP3PHeader, _dwPrivacyFlags);
  773. cleanup:
  774. if (!SUCCEEDED(hRes))
  775. {
  776. delete [] pszUrl;
  777. }
  778. return hRes;
  779. }
  780. void CDocObjectHost::CDOHBindStatusCallback::_Redirect(LPCWSTR pwzNew)
  781. {
  782. LPITEMIDLIST pidlNew;
  783. WCHAR wszPath[MAX_URL_STRING] = TEXT("");
  784. CDocObjectHost* pdoh = IToClass(CDocObjectHost, _bsc, this);
  785. LPOLESTR pwszCurrent = NULL;
  786. BOOL fAllow = FALSE;
  787. if (SUCCEEDED(IECreateFromPath(pwzNew, &pidlNew))) {
  788. TraceMsg(TF_SHDNAVIGATE, "CDOH::CBSC::_Redirect calling NotifyRedirect(%s)", pwzNew);
  789. if ( pdoh->_pwb )
  790. {
  791. pdoh->_pwb->NotifyRedirect(pdoh->_psv, pidlNew, NULL);
  792. }
  793. // Important - Do this before we destroy the old redirect url
  794. BuildRecord();
  795. ResetPrivacyInfo();
  796. // Save te redirected URL
  797. if (_pszRedirectedURL)
  798. LocalFree( _pszRedirectedURL );
  799. _pszRedirectedURL = StrDup(pwzNew);
  800. // We need to account for a bookmark that might appear
  801. // in the redirected URL.
  802. if(IEILGetFragment(pidlNew, wszPath, SIZECHARS(wszPath))) {
  803. LocalFree((LPVOID) pdoh->_pszLocation);
  804. pdoh->_pszLocation = StrDup(wszPath);
  805. }
  806. ILFree(pidlNew);
  807. }
  808. AddUrlToUrlHistoryStg(pwzNew, NULL, pdoh->_psb, FALSE,
  809. NULL, NULL, NULL);
  810. // Security: Release the pre-created object and start over for
  811. // server-side redirects. The only security check for the
  812. // document reference occurs when someone tries to obtain it.
  813. // Therefore, we want to orphan the reference if x-domain, so the
  814. // client will need to obtain a new reference to the redirected
  815. // document.
  816. if (SUCCEEDED(pdoh->_GetCurrentPageW(&pwszCurrent, TRUE)))
  817. {
  818. fAllow = AccessAllowed(pwszCurrent, pwzNew);
  819. OleFree(pwszCurrent);
  820. }
  821. if (!fAllow)
  822. pdoh->_ReleasePendingObject(FALSE);
  823. }
  824. //
  825. // In this function, we get the codepage for the current URL. If that's not
  826. // CP_ACP, we pass it to Trident via IBindCtx*.
  827. //
  828. void CDocObjectHost::CDOHBindStatusCallback::_CheckForCodePageAndShortcut(void)
  829. {
  830. CDocObjectHost* pdoh = IToClass(CDocObjectHost, _bsc, this);
  831. LPWSTR pwszURL;
  832. HRESULT hres = pdoh->_GetCurrentPageW(&pwszURL, TRUE);
  833. if (SUCCEEDED(hres)) {
  834. UINT codepage = CP_ACP;
  835. IOleCommandTarget *pcmdt;
  836. VARIANT varShortCutPath = {0};
  837. BOOL fHasShortcut = FALSE;
  838. hres = pdoh->QueryService(SID_SHlinkFrame, IID_IOleCommandTarget, (void **)&pcmdt);
  839. if(S_OK == hres)
  840. {
  841. ASSERT(pcmdt);
  842. hres = pcmdt->Exec(&CGID_Explorer, SBCMDID_GETSHORTCUTPATH, 0, NULL, &varShortCutPath);
  843. //
  844. // App Compat: Imagineer Technical returns S_OK for the above Exec
  845. // but of course doesn't set the output parameter.
  846. //
  847. if((S_OK) == hres && VT_BSTR == varShortCutPath.vt && varShortCutPath.bstrVal)
  848. {
  849. fHasShortcut = TRUE;
  850. }
  851. pcmdt->Release();
  852. }
  853. if(UrlHitsNetW(pwszURL))
  854. {
  855. // Don't do this for File: files - we can live
  856. // with getting the code page late for file: even
  857. // if it slows down file: display somewhat if the
  858. // trident parser needs to restarted
  859. AddUrlToUrlHistoryStg(pwszURL, NULL, pdoh->_psb, FALSE,
  860. NULL, NULL, &codepage);
  861. }
  862. TraceMsg(DM_DOCCP, "CDOH::CBSC::_CheckForCodePageAndShortcut codepage=%d", codepage);
  863. if ((codepage != CP_ACP || fHasShortcut) && _pbc) {
  864. // Here is where we pass the codepage to Trident.
  865. // (Mars): Clients may have already registered HtmlLoadOptions with
  866. // the bind context in order to specify the shortcut path. In this case,
  867. // registering it again to set the codepage would fail. However, we should
  868. // first verify that this codepage stuff actually gets used.
  869. IHtmlLoadOptions *phlo;
  870. HRESULT hres = CoCreateInstance(CLSID_HTMLLoadOptions,
  871. NULL, CLSCTX_INPROC_SERVER,
  872. IID_IHtmlLoadOptions, (void**)&phlo);
  873. if (SUCCEEDED(hres) && phlo)
  874. {
  875. if(codepage != CP_ACP)
  876. {
  877. hres = phlo->SetOption(HTMLLOADOPTION_CODEPAGE, &codepage, sizeof(codepage));
  878. }
  879. if (SUCCEEDED(hres))
  880. {
  881. if(fHasShortcut)
  882. {
  883. // deliberately ignore failures here
  884. phlo->SetOption(HTMLLOADOPTION_INETSHORTCUTPATH, varShortCutPath.bstrVal,
  885. (lstrlenW(varShortCutPath.bstrVal) + 1)*sizeof(WCHAR));
  886. }
  887. _pbc->RegisterObjectParam(L"__HTMLLOADOPTIONS", phlo);
  888. }
  889. phlo->Release();
  890. } else {
  891. TraceMsg(DM_WARNING, "DOH::_CheckForCodePagecut CoCreateInst failed (%x)", hres);
  892. }
  893. }
  894. VariantClear(&varShortCutPath);
  895. OleFree(pwszURL);
  896. }
  897. }
  898. #ifdef BETA1_DIALMON_HACK
  899. extern void IndicateWinsockActivity();
  900. #endif // BETA1_DIALMON_HACK
  901. HRESULT CDocObjectHost::CDOHBindStatusCallback::OnProgress(
  902. ULONG ulProgress,
  903. ULONG ulProgressMax,
  904. ULONG ulStatusCode,
  905. LPCWSTR pwzStatusText)
  906. {
  907. HRESULT hr = S_OK;
  908. HRESULT hrPrivacy = S_OK;
  909. TCHAR * pszPrivacyURL = NULL;
  910. static TCHAR * pszNULL = NULL;
  911. TraceMsg(TF_SHDPROGRESS, "DOH::BSC::OnProgress (%d of %d) ulStatus=%x",
  912. ulProgress, ulProgressMax, ulStatusCode);
  913. // JEFFWE 4/15/96 Beta 1 Hack - every once in a while, send message
  914. // to the hidden window that detects inactivity so that it doesn't
  915. // think we are inactive during a long download
  916. #ifdef BETA1_DIALMON_HACK
  917. IndicateWinsockActivity();
  918. #endif
  919. CDocObjectHost * pdoh = IToClass(CDocObjectHost, _bsc, this);
  920. #ifdef DEBUG
  921. if (pwzStatusText)
  922. {
  923. char szStatusText[MAX_PATH]; // OK with MAX_PATH
  924. UnicodeToAnsi(pwzStatusText, szStatusText, ARRAYSIZE(szStatusText));
  925. TraceMsg(TF_SHDPROGRESS, "DOH::BSC::OnProgress pszStatus=%s", szStatusText);
  926. }
  927. #endif
  928. if (pdoh->_psb)
  929. {
  930. // we may be switching between multiple proxy/server hosts, so don't prevent
  931. // showing them when they change
  932. if (_bindst != ulStatusCode ||
  933. ulStatusCode == BINDSTATUS_FINDINGRESOURCE)
  934. {
  935. UINT idRes = IDI_STATE_NORMAL;
  936. _bindst = ulStatusCode;
  937. if (_bindst < ARRAYSIZE(c_aidRes))
  938. idRes = c_aidRes[_bindst];
  939. pdoh->_psb->SendControlMsg(FCW_STATUS, SB_SETICON, STATUS_PANE_NAVIGATION,
  940. (LPARAM)g_ahiconState[idRes-IDI_STATE_FIRST], NULL);
  941. TCHAR szStatusText[MAX_PATH]; // OK with MAX_PATH
  942. if (pwzStatusText)
  943. {
  944. StrCpyN(szStatusText, pwzStatusText, ARRAYSIZE(szStatusText));
  945. }
  946. else
  947. {
  948. szStatusText[0] = TEXT('\0');
  949. }
  950. //
  951. // This if-block will open the safe open dialog for OLE Object
  952. // and DocObject.
  953. //
  954. if (_bindst == BINDSTATUS_CLASSIDAVAILABLE)
  955. {
  956. TraceMsg(TF_SHDPROGRESS, "DOH::BSC::OnProgress got CLSID=%ws", szStatusText);
  957. CLSID clsid;
  958. // WORK-AROUND: CLSIDFromString does not take LPCOLESTR correctly.
  959. HRESULT hresT = CLSIDFromString((LPOLESTR)pwzStatusText, &clsid);
  960. if (SUCCEEDED(hresT))
  961. {
  962. #ifdef DEBUG
  963. if (IsEqualGUID(clsid, CLSID_NULL))
  964. {
  965. TraceMsg(DM_WARNING, "DOH::SBC::OnProgress Got CLSID_NULL");
  966. }
  967. #endif
  968. //
  969. // Notice that we don't want to use BROWSERFLAG_MSHTML,
  970. // which includes other types of MSHMTL CLSIDs.
  971. // In this case, we just want to deal with HTMLDocument.
  972. // (We allow XMLViewer docobj and *.MHT and *.MHTML too!)
  973. BOOL fIsHTML = (IsEqualGUID(clsid, CLSID_HTMLDocument) ||
  974. IsEqualGUID(clsid, CLSID_XMLViewerDocObj) ||
  975. IsEqualGUID(clsid, CLSID_MHTMLDocument));
  976. BOOL fAbortDesktopComponent = FALSE;
  977. if(!fIsHTML)
  978. {
  979. //Check if we are a desktop component.
  980. if (_IsDesktopItem(pdoh))
  981. {
  982. //Because this is NOT html, then don't show it!
  983. fAbortDesktopComponent = TRUE;
  984. }
  985. }
  986. if (fAbortDesktopComponent)
  987. {
  988. AbortBinding();
  989. hr = E_ABORT;
  990. }
  991. else
  992. {
  993. _fBoundToMSHTML = fIsHTML; // Remember this and suppress redundant
  994. // AddUrl to history
  995. // There is an interval of time between OnProgress and OnObjectAvailable
  996. // in which the om might be required.
  997. if (fIsHTML && pdoh->_punkPending == NULL)
  998. {
  999. pdoh->_CreatePendingDocObject(FALSE);
  1000. }
  1001. if (pdoh->_punkPending)
  1002. {
  1003. IPersist *pip;
  1004. hresT = pdoh->_punkPending->QueryInterface(IID_IPersist, (LPVOID *) &pip);
  1005. if (SUCCEEDED(hresT))
  1006. {
  1007. CLSID clsidPending;
  1008. hresT = pip->GetClassID(&clsidPending);
  1009. if (SUCCEEDED(hresT) && IsEqualGUID(clsid, clsidPending))
  1010. {
  1011. _pbc->RegisterObjectParam(L"__PrecreatedObject", pdoh->_punkPending);
  1012. }
  1013. pip->Release();
  1014. }
  1015. }
  1016. hresT = pdoh->_MayHaveVirus(clsid);
  1017. if (hresT == HRESULT_FROM_WIN32(ERROR_CANCELLED))
  1018. {
  1019. hr = E_ABORT;
  1020. AbortBinding();
  1021. if (pdoh->_pmsoctBrowser && pdoh->_fWindowOpen)
  1022. {
  1023. pdoh->_pmsoctBrowser->Exec(&CGID_Explorer, SBCMDID_CANCELANDCLOSE, 0, NULL, NULL);
  1024. }
  1025. }
  1026. }
  1027. }
  1028. else
  1029. {
  1030. TraceMsg(DM_ERROR, "DOH::BSC::OnProgress CLSIDFromString failed %x", hresT);
  1031. }
  1032. //
  1033. // Notice that URLMON will call IPersistMoniker::Load right
  1034. // after we return from this notification. Therefore, this
  1035. // is the latest moment we have a chance to pass the code
  1036. // page to Trident.
  1037. //
  1038. _CheckForCodePageAndShortcut();
  1039. }
  1040. else if (_bindst == BINDSTATUS_CACHEFILENAMEAVAILABLE)
  1041. {
  1042. TraceMsg(DM_SELFASC, "DOH::OnProgress got BINDSTATUS_CACHEFILENAMEAVAILABLE");
  1043. _fSelfAssociated = IsAssociatedWithIE(pwzStatusText);
  1044. if(_pszCacheFileName)
  1045. LocalFree(_pszCacheFileName);
  1046. _pszCacheFileName = StrDup(pwzStatusText);
  1047. }
  1048. else if (_bindst == BINDSTATUS_CONTENTDISPOSITIONATTACH)
  1049. {
  1050. TCHAR szURL[MAX_URL_STRING];
  1051. TCHAR * pszURL = szURL;
  1052. HRESULT hresT;
  1053. hresT = pdoh->_GetCurrentPage(szURL, ARRAYSIZE(szURL), TRUE);
  1054. if (SUCCEEDED(hresT))
  1055. {
  1056. UINT uRet;
  1057. if (_pszRedirectedURL && lstrlen(_pszRedirectedURL))
  1058. {
  1059. pszURL = _pszRedirectedURL;
  1060. }
  1061. IUnknown * punk;
  1062. hresT = pdoh->QueryInterface(IID_IUnknown, (void**)&punk);
  1063. if (SUCCEEDED(hresT))
  1064. {
  1065. uRet = OpenSafeOpenDialog(pdoh->_hwnd, DLG_SAFEOPEN, NULL, pszURL, NULL, szStatusText, NULL, pdoh->_uiCP, punk);
  1066. switch(uRet)
  1067. {
  1068. case IDOK:
  1069. //
  1070. // Set this flag to avoid poppping this dialog box twice.
  1071. //
  1072. pdoh->_fConfirmed = TRUE;
  1073. break; // continue download
  1074. case IDD_SAVEAS:
  1075. CDownLoad_OpenUI(pdoh->_pmkCur, _pbc, FALSE, TRUE, NULL, NULL, NULL, NULL, NULL, _pszRedirectedURL, pdoh->_uiCP, punk);
  1076. ATOMICRELEASE(_pbc);
  1077. ATOMICRELEASE(_psvPrev);
  1078. // fall thru to AbortBinding
  1079. case IDCANCEL:
  1080. pdoh->_CancelPendingNavigation(FALSE);
  1081. AbortBinding();
  1082. if (uRet == IDCANCEL)
  1083. {
  1084. _fAborted = TRUE;
  1085. }
  1086. break;
  1087. }
  1088. punk->Release();
  1089. }
  1090. }
  1091. }
  1092. if ( ( _bindst >= BINDSTATUS_FINDINGRESOURCE
  1093. && _bindst <= BINDSTATUS_SENDINGREQUEST)
  1094. || _bindst == BINDSTATUS_PROXYDETECTING)
  1095. {
  1096. TCHAR szTemplate[MAX_PATH]; // OK with MAX_PATH
  1097. UINT idResource = IDS_BINDSTATUS+_bindst;
  1098. if ( _bindst == BINDSTATUS_PROXYDETECTING )
  1099. {
  1100. idResource = IDS_BINDSTATUS_PROXYDETECTING;
  1101. }
  1102. // If we are connecting over proxy, don't say "web site found".
  1103. //
  1104. if (fOnProxy() && idResource == IDS_BINDSTATUS_SEND)
  1105. {
  1106. idResource = IDS_BINDSTATUS_CON;
  1107. TCHAR szUrl[MAX_URL_STRING];
  1108. pdoh->_GetCurrentPage(szUrl, SIZECHARS(szUrl));
  1109. DWORD cchStatusText = SIZECHARS(szStatusText);
  1110. UrlGetPart(szUrl, szStatusText, &cchStatusText, URL_PART_HOSTNAME, 0);
  1111. }
  1112. if (MLLoadString(idResource, szTemplate, ARRAYSIZE(szTemplate)))
  1113. {
  1114. BSCMSGS("OnProgress szTemplate=", szTemplate);
  1115. TCHAR szMessage[MAX_PATH]; // OK with MAX_PATH
  1116. BOOL fSuccess = wnsprintf(szMessage, ARRAYSIZE(szMessage), szTemplate, szStatusText);
  1117. if (fSuccess)
  1118. {
  1119. BSCMSGS("OnProgress szMessage=", szMessage);
  1120. pdoh->_SetStatusText(szMessage);
  1121. }
  1122. }
  1123. }
  1124. }
  1125. DWORD dwState = 0;
  1126. switch (ulStatusCode)
  1127. {
  1128. case BINDSTATUS_REDIRECTING:
  1129. // they're redirecting. treat this as a rename.
  1130. _Redirect(pwzStatusText);
  1131. break;
  1132. case BINDSTATUS_FINDINGRESOURCE:
  1133. dwState = PROGRESS_FINDING;
  1134. ASSERT(!ulProgressMax);
  1135. break;
  1136. case BINDSTATUS_SENDINGREQUEST:
  1137. dwState = PROGRESS_SENDING;
  1138. ASSERT(!ulProgressMax);
  1139. break;
  1140. //Handle privacy notifications
  1141. case BINDSTATUS_COOKIE_SENT:
  1142. BSCMSG(TEXT("OnProgress - Received BINDSTATUS_COOKIE_SENT"), 0 ,0);
  1143. if (pwzStatusText && *pwzStatusText)
  1144. {
  1145. pszPrivacyURL = new TCHAR[MAX_URL_STRING];
  1146. if (!pszPrivacyURL)
  1147. break;
  1148. StrCpyN(pszPrivacyURL, pwzStatusText, MAX_URL_STRING);
  1149. hrPrivacy = AddToPrivacyQueue(&pszPrivacyURL, &pszNULL, &pszNULL, COOKIEACTION_READ);
  1150. if (!SUCCEEDED(hrPrivacy))
  1151. delete [] pszPrivacyURL;
  1152. }
  1153. else
  1154. {
  1155. _dwPrivacyFlags |= COOKIEACTION_READ;
  1156. }
  1157. break;
  1158. case BINDSTATUS_COOKIE_SUPPRESSED:
  1159. BSCMSG(TEXT("OnProgress - Received BINDSTATUS_COOKIE_SUPPRESSED"), 0, 0);
  1160. if (pwzStatusText && *pwzStatusText)
  1161. {
  1162. pszPrivacyURL = new TCHAR[MAX_URL_STRING];
  1163. if (!pszPrivacyURL)
  1164. break;
  1165. StrCpyN(pszPrivacyURL, pwzStatusText, MAX_URL_STRING);
  1166. hrPrivacy = AddToPrivacyQueue(&pszPrivacyURL, &pszNULL, &pszNULL, COOKIEACTION_SUPPRESS);
  1167. if (!SUCCEEDED(hrPrivacy))
  1168. delete [] pszPrivacyURL;
  1169. }
  1170. else
  1171. {
  1172. _dwPrivacyFlags |= COOKIEACTION_SUPPRESS;
  1173. }
  1174. break;
  1175. case BINDSTATUS_COOKIE_STATE_UNKNOWN:
  1176. BSCMSG(TEXT("Shdocvw should never BINDSTATUS_COOKIE_STATE_UNKNOWN from Wininet/Urlmon"), 0, 0);
  1177. break;
  1178. case BINDSTATUS_COOKIE_STATE_ACCEPT:
  1179. BSCMSG(TEXT("OnProgress - Received BINDSTATUS_COOKIE_STATE_ACCEPT"), 0, 0);
  1180. if (pwzStatusText && *pwzStatusText)
  1181. {
  1182. pszPrivacyURL = new TCHAR[MAX_URL_STRING];
  1183. if (!pszPrivacyURL)
  1184. break;
  1185. StrCpyN(pszPrivacyURL, pwzStatusText, MAX_URL_STRING);
  1186. hrPrivacy = AddToPrivacyQueue(&pszPrivacyURL, &pszNULL, &pszNULL, COOKIEACTION_ACCEPT);
  1187. if (!SUCCEEDED(hrPrivacy))
  1188. delete [] pszPrivacyURL;
  1189. }
  1190. else
  1191. {
  1192. _dwPrivacyFlags |= COOKIEACTION_ACCEPT;
  1193. }
  1194. break;
  1195. case BINDSTATUS_COOKIE_STATE_REJECT:
  1196. BSCMSG(TEXT("OnProgress - Received BINDSTATUS_COOKIE_STATE_REJECT"), 0, 0);
  1197. if (pwzStatusText && *pwzStatusText)
  1198. {
  1199. pszPrivacyURL = new TCHAR[MAX_URL_STRING];
  1200. if (!pszPrivacyURL)
  1201. break;
  1202. StrCpyN(pszPrivacyURL, pwzStatusText, MAX_URL_STRING);
  1203. hrPrivacy = AddToPrivacyQueue(&pszPrivacyURL, &pszNULL, &pszNULL, COOKIEACTION_REJECT);
  1204. if (!SUCCEEDED(hrPrivacy))
  1205. delete [] pszPrivacyURL;
  1206. }
  1207. else
  1208. {
  1209. _dwPrivacyFlags |= COOKIEACTION_REJECT;
  1210. }
  1211. break;
  1212. case BINDSTATUS_COOKIE_STATE_PROMPT:
  1213. BSCMSG(TEXT("Shdocvw should never BINDSTATUS_COOKIE_STATE_PROMPT from Wininet/Urlmon"), 0, 0);
  1214. break;
  1215. case BINDSTATUS_COOKIE_STATE_LEASH:
  1216. BSCMSG(TEXT("OnProgress - Received BINDSTATUS_COOKIE_STATE_LEASH"), 0, 0);
  1217. if (pwzStatusText && *pwzStatusText)
  1218. {
  1219. pszPrivacyURL = new TCHAR[MAX_URL_STRING];
  1220. if (!pszPrivacyURL)
  1221. break;
  1222. StrCpyN(pszPrivacyURL, pwzStatusText, MAX_URL_STRING);
  1223. hrPrivacy = AddToPrivacyQueue(&pszPrivacyURL, &pszNULL, &pszNULL, COOKIEACTION_LEASH);
  1224. if (!SUCCEEDED(hrPrivacy))
  1225. delete [] pszPrivacyURL;
  1226. }
  1227. else
  1228. {
  1229. _dwPrivacyFlags |= COOKIEACTION_LEASH;
  1230. }
  1231. break;
  1232. case BINDSTATUS_COOKIE_STATE_DOWNGRADE:
  1233. BSCMSG(TEXT("OnProgress - Received BINDSTATUS_COOKIE_STATE_DOWNGRADE"), 0, 0);
  1234. if (pwzStatusText && *pwzStatusText)
  1235. {
  1236. pszPrivacyURL = new TCHAR[MAX_URL_STRING];
  1237. if (!pszPrivacyURL)
  1238. break;
  1239. StrCpyN(pszPrivacyURL, pwzStatusText, MAX_URL_STRING);
  1240. hrPrivacy = AddToPrivacyQueue(&pszPrivacyURL, &pszNULL, &pszNULL, COOKIEACTION_DOWNGRADE);
  1241. if (!SUCCEEDED(hrPrivacy))
  1242. delete [] pszPrivacyURL;
  1243. }
  1244. else
  1245. {
  1246. _dwPrivacyFlags |= COOKIEACTION_DOWNGRADE;
  1247. }
  1248. break;
  1249. case BINDSTATUS_COMPACT_POLICY_RECEIVED:
  1250. _dwPrivacyFlags |= PRIVACY_URLHASCOMPACTPOLICY;
  1251. break;
  1252. case BINDSTATUS_POLICY_HREF:
  1253. BSCMSG(TEXT("OnProgress - Received BINDSTATUS_POLICY_HREF"), 0, 0);
  1254. ASSERT(pwzStatusText && *pwzStatusText);
  1255. // We are getting two notifications from urlmon, once that is fixed, need to uncomment this assert
  1256. //ASSERT(!_pszPolicyRefURL);
  1257. if (_pszPolicyRefURL)
  1258. {
  1259. LocalFree(_pszPolicyRefURL);
  1260. }
  1261. _pszPolicyRefURL = StrDup(pwzStatusText);
  1262. _dwPrivacyFlags |= PRIVACY_URLHASPOLICYREFHEADER;
  1263. break;
  1264. case BINDSTATUS_P3P_HEADER:
  1265. BSCMSG(TEXT("OnProgress - Received BINDSTATUS_P3P_HEADER"), 0, 0);
  1266. ASSERT(pwzStatusText && *pwzStatusText);
  1267. // We are getting two notifications from urlmon, once that is fixed, need to uncomment this assert
  1268. //ASSERT(!_pszP3PHeader);
  1269. if (_pszP3PHeader)
  1270. {
  1271. LocalFree(_pszP3PHeader);
  1272. }
  1273. _pszP3PHeader = StrDup(pwzStatusText);
  1274. _dwPrivacyFlags |= PRIVACY_URLHASP3PHEADER;
  1275. break;
  1276. }
  1277. if (dwState)
  1278. {
  1279. pdoh->_OnSetProgressPos(ulProgress, dwState);
  1280. }
  1281. if (BINDSTATUS_BEGINDOWNLOADDATA == ulStatusCode)
  1282. {
  1283. _cbContentLength = ulProgress;
  1284. }
  1285. else if (BINDSTATUS_MIMETYPEAVAILABLE == ulStatusCode)
  1286. {
  1287. // delegate to media bar if this is a media mime-type
  1288. if ( pwzStatusText
  1289. && ( !StrCmpNIW(pwzStatusText, _T("audio"), 5)
  1290. || !StrCmpNIW(pwzStatusText, _T("video"), 5)))
  1291. {
  1292. if (pdoh->_DelegateToMediaBar(NULL, pwzStatusText))
  1293. {
  1294. // Cancel the navigation
  1295. pdoh->_CancelPendingNavigation(FALSE);
  1296. AbortBinding();
  1297. _fAborted = TRUE;
  1298. if (pdoh->_pwb)
  1299. {
  1300. pdoh->_pwb->SetNavigateState(BNS_NORMAL);
  1301. }
  1302. }
  1303. }
  1304. }
  1305. }
  1306. #ifndef NO_DELEGATION
  1307. if (_pbscChained)
  1308. {
  1309. _pbscChained->OnProgress(ulProgress, ulProgressMax, ulStatusCode, pwzStatusText);
  1310. }
  1311. #endif
  1312. return hr;
  1313. }
  1314. HRESULT CDocObjectHost::CDOHBindStatusCallback::OnDataAvailable(
  1315. /* [in] */ DWORD grfBSC,
  1316. /* [in] */ DWORD dwSize,
  1317. /* [in] */ FORMATETC *pformatetc,
  1318. /* [in] */ STGMEDIUM *pstgmed)
  1319. {
  1320. BSCMSG(TEXT("OnDataAvailable (grf,pstg)"), grfBSC, pstgmed);
  1321. #ifndef NO_DELEGATION
  1322. if (_pbscChained)
  1323. {
  1324. _pbscChained->OnDataAvailable(grfBSC, dwSize, pformatetc, pstgmed);
  1325. }
  1326. #endif
  1327. return S_OK;
  1328. }
  1329. void CDocObjectHost::CDOHBindStatusCallback::_UpdateSSLIcon(void)
  1330. {
  1331. CDocObjectHost* pdoh = IToClass(CDocObjectHost, _bsc, this);
  1332. ASSERT(_pib);
  1333. //
  1334. // if we have already been set by our object, we dont
  1335. // want to override it.
  1336. if (_pib && !pdoh->_fSetSecureLock)
  1337. {
  1338. pdoh->_eSecureLock = SECURELOCK_SET_UNSECURE;
  1339. IWinInetInfo* pwinet;
  1340. HRESULT hresT = _pib->QueryInterface(IID_IWinInetInfo, (LPVOID*)&pwinet);
  1341. if (SUCCEEDED(hresT))
  1342. {
  1343. DWORD dwOptions = 0;
  1344. DWORD cbSize = SIZEOF(dwOptions);
  1345. hresT = pwinet->QueryOption(INTERNET_OPTION_SECURITY_FLAGS,
  1346. (LPVOID)&dwOptions, &cbSize);
  1347. TraceMsg(DM_SSL, "pwinet->QueryOptions hres=%x dwOptions=%x", hresT, dwOptions);
  1348. if (SUCCEEDED(hresT))
  1349. {
  1350. LPWSTR pwzUrl;
  1351. pdoh->_fSetSecureLock = TRUE;
  1352. if(dwOptions & SECURITY_FLAG_SECURE)
  1353. {
  1354. pdoh->_dwSecurityStatus = dwOptions;
  1355. if (pdoh->_dwSecurityStatus & SECURITY_FLAG_40BIT)
  1356. {
  1357. pdoh->_eSecureLock = SECURELOCK_SET_SECURE40BIT;
  1358. }
  1359. else if (pdoh->_dwSecurityStatus & SECURITY_FLAG_128BIT)
  1360. {
  1361. pdoh->_eSecureLock = SECURELOCK_SET_SECURE128BIT;
  1362. }
  1363. else if (pdoh->_dwSecurityStatus & SECURITY_FLAG_FORTEZZA)
  1364. {
  1365. pdoh->_eSecureLock = SECURELOCK_SET_FORTEZZA;
  1366. }
  1367. else if (pdoh->_dwSecurityStatus & SECURITY_FLAG_56BIT)
  1368. {
  1369. pdoh->_eSecureLock = SECURELOCK_SET_SECURE56BIT;
  1370. }
  1371. }
  1372. else if (SUCCEEDED(_GetRequestFlagFromPIB(_pib, &dwOptions)) &&
  1373. (dwOptions & INTERNET_REQFLAG_FROM_CACHE) &&
  1374. SUCCEEDED(pdoh->_GetCurrentPageW(&pwzUrl, TRUE)))
  1375. {
  1376. //
  1377. // when secure pages are cached, they lose their
  1378. // security context, but should still be displayed
  1379. // as secure. therefore we use the UnknownBit level
  1380. // of security.
  1381. //
  1382. if(URL_SCHEME_HTTPS == GetUrlSchemeW(pwzUrl))
  1383. pdoh->_eSecureLock = SECURELOCK_SET_SECUREUNKNOWNBIT;
  1384. OleFree(pwzUrl);
  1385. }
  1386. }
  1387. else
  1388. {
  1389. pdoh->_dwSecurityStatus = 0;
  1390. }
  1391. // we will update the browser when we are activated
  1392. pwinet->Release();
  1393. }
  1394. else
  1395. {
  1396. TraceMsg(DM_SSL, "QI to IWinInetInfo failed");
  1397. }
  1398. TraceMsg(DM_SSL, "[%X] UpdateSslIcon() setting _eSecureLock = %d", pdoh, pdoh->_eSecureLock);
  1399. }
  1400. else
  1401. {
  1402. TraceMsg(DM_SSL, "[%X] UpdateSslIcon() already set _eSecureLock = %d", pdoh, pdoh->_eSecureLock);
  1403. }
  1404. }
  1405. HRESULT CDocObjectHost::CDOHBindStatusCallback::OnObjectAvailable(
  1406. /* [in] */ REFIID riid,
  1407. /* [iid_is][in] */ IUnknown *punk)
  1408. {
  1409. BSCMSG(TEXT("OnObjectAvailable (riid,punk)"), riid, punk);
  1410. CDocObjectHost * pdoh = IToClass(CDocObjectHost, _bsc, this);
  1411. #ifdef DEBUG
  1412. extern DWORD g_dwPerf;
  1413. PERFMSG(TEXT("OnObjectAvailable called"), GetCurrentTime()-g_dwPerf);
  1414. g_dwPerf = GetCurrentTime();
  1415. #endif
  1416. // If we get this far, DocObject has been inited by UrlMon or
  1417. // in process of retrieving pending object via IOleCommandTarget::Exec()
  1418. if (pdoh->_punkPending)
  1419. {
  1420. pdoh->_fPendingNeedsInit = 0;
  1421. }
  1422. //
  1423. // When this notification is called first time, we should ask
  1424. // the browser to activate us (which causes BindToObject).
  1425. //
  1426. if (pdoh->_pole==NULL && punk)
  1427. {
  1428. HRESULT hresT = punk->QueryInterface(IID_IOleObject, (LPVOID*)&(pdoh->_pole));
  1429. if (SUCCEEDED(hresT))
  1430. {
  1431. IOleDocument * pmsod = NULL;
  1432. pdoh->_OnBound(S_OK);
  1433. hresT = (pdoh->_fDontInPlaceNavigate() ? E_NOINTERFACE : punk->QueryInterface(IID_IOleDocument, (LPVOID*)&pmsod));
  1434. if (SUCCEEDED(hresT))
  1435. {
  1436. pmsod->Release(); // We don't use it at this point.
  1437. // Case 1: DocObject
  1438. OPENMSG(TEXT("OnObjectAvailable ASYNC DocObject"));
  1439. ASSERT(pdoh->_psb);
  1440. if (pdoh->_pmsoctBrowser)
  1441. {
  1442. VARIANT var = {0};
  1443. VARIANT varOut = {0};
  1444. // Tell the host that we know this is a document object.
  1445. V_VT(&var) = VT_BOOL;
  1446. V_BOOL(&var) = VARIANT_TRUE;
  1447. pdoh->_pmsoctBrowser->Exec(&CGID_ShellDocView, SHDVID_FIREFILEDOWNLOAD, 0, &var, &varOut);
  1448. }
  1449. #ifdef FEATURE_PICS
  1450. BOOL fSupportsPICS = FALSE;
  1451. if (pdoh->_PicsProcBase._fbPicsWaitFlags)
  1452. {
  1453. VARIANTARG v;
  1454. v.vt = VT_UNKNOWN;
  1455. v.byref = (LPVOID)(IOleCommandTarget *)&pdoh->_PicsProcBase;
  1456. hresT = IUnknown_Exec(pdoh->_pole, &CGID_ShellDocView, SHDVID_CANSUPPORTPICS, 0, &v, NULL);
  1457. if (hresT == S_OK)
  1458. {
  1459. BSCMSG(TEXT("OnObjectAvailable - obj supports PICS"), 0, 0);
  1460. fSupportsPICS = TRUE;
  1461. }
  1462. else
  1463. {
  1464. BSCMSG(TEXT("OnObjectAvailable - obj either doesn't support IOleCommandTarget or doesn't support PICS"), hresT, 0);
  1465. }
  1466. }
  1467. #endif
  1468. BSCMSG(TEXT("OnObjectAvailable calling pdoh->_Navigate"), 0, 0);
  1469. pdoh->_SetUpTransitionCapability();
  1470. _UpdateSSLIcon();
  1471. #ifdef FEATURE_PICS
  1472. // If we can't get labels out of the document (or don't need
  1473. // to, because we already got one from a bureau or HTTP header),
  1474. // see if we can complete PICS checking now.
  1475. //
  1476. if (!fSupportsPICS)
  1477. {
  1478. pdoh->_PicsProcBase._fbPicsWaitFlags &= ~(PICS_WAIT_FOR_INDOC | PICS_WAIT_FOR_END); /* no indoc ratings */
  1479. if (!pdoh->_PicsProcBase._fbPicsWaitFlags)
  1480. {
  1481. TraceMsg(DM_PICS, "OnObjectAvailable calling _HandlePicsChecksComplete");
  1482. pdoh->_PicsProcBase._HandlePicsChecksComplete();
  1483. }
  1484. }
  1485. #endif
  1486. }
  1487. else
  1488. {
  1489. // Case 2: OLE object
  1490. OPENMSG(TEXT("OnDataAvailable ASYNC OLE Object"));
  1491. pdoh->_ActivateOleObject();
  1492. // We need to tell the browser not to add this one to the
  1493. // browse history.
  1494. // We also want to close the browser window if this is the first
  1495. // download - that's why we pass TRUE - to treat it like a code
  1496. // download
  1497. //
  1498. if (pdoh->_dwAppHack & BROWSERFLAG_DONTAUTOCLOSE)
  1499. {
  1500. pdoh->_CancelPendingNavigation(FALSE);
  1501. }
  1502. else
  1503. {
  1504. pdoh->_CancelPendingNavigation(TRUE, FALSE, FALSE, TRUE);
  1505. }
  1506. if (pdoh->_fDelegatedNavigation)
  1507. {
  1508. VARIANT varOut = {0};
  1509. IDocNavigate * pDocNavigate;
  1510. pdoh->_pmsoctBrowser->Exec(&CGID_ShellDocView,
  1511. SHDVID_FIREFILEDOWNLOAD,
  1512. 0, NULL, &varOut);
  1513. HRESULT hr = E_FAIL;
  1514. if ( pdoh->_pwb )
  1515. {
  1516. hr = pdoh->_pwb->QueryInterface(IID_PPV_ARG(IDocNavigate, &pDocNavigate));
  1517. }
  1518. if (S_OK == hr)
  1519. {
  1520. pDocNavigate->OnReadyStateChange(NULL, READYSTATE_COMPLETE);
  1521. pDocNavigate->Release();
  1522. }
  1523. }
  1524. //
  1525. // If this is the very first page, we should draw the background.
  1526. //
  1527. pdoh->_fDrawBackground = TRUE;
  1528. //If the following assert is hit, then that means that we are
  1529. // going to invalidate the desktop window (which is not
  1530. // intended here)
  1531. //
  1532. ASSERT(pdoh->_hwnd);
  1533. InvalidateRect(pdoh->_hwnd, NULL, TRUE);
  1534. }
  1535. }
  1536. else
  1537. {
  1538. _fBoundToNoOleObject = TRUE;
  1539. }
  1540. }
  1541. // Add privacy info to Trident's list if possible
  1542. if (_fBoundToMSHTML)
  1543. {
  1544. HRESULT hRes = E_FAIL;
  1545. IServiceProvider * pSP = NULL;
  1546. IPrivacyServices * pPrivacyServices = NULL;
  1547. DWORD dwTopLevelFlag = 0;
  1548. // QueryService the Trident for the IPrivacyServices interface
  1549. hRes = pdoh->_pole->QueryInterface(IID_IServiceProvider, (void**)&pSP);
  1550. if (SUCCEEDED(hRes) && pSP)
  1551. {
  1552. hRes = pSP->QueryService(IID_IPrivacyServices,IID_IPrivacyServices,(void**)&pPrivacyServices);
  1553. pSP->Release();
  1554. }
  1555. if (pPrivacyServices)
  1556. {
  1557. if (pdoh->_psp && pdoh->_psb && IsTopFrameBrowser(pdoh->_psp, pdoh->_psb))
  1558. {
  1559. dwTopLevelFlag |= PRIVACY_URLISTOPLEVEL;
  1560. }
  1561. // Add dummy marker since Trident would have added its records during the BindToStorage call
  1562. // initiated due to shdocvw's current bind only if we are top level
  1563. if (dwTopLevelFlag)
  1564. pPrivacyServices->AddPrivacyInfoToList( TEXT(""), NULL, NULL, 0, PRIVACY_URLISTOPLEVEL);
  1565. // Add each item in the privacy queue (accumulated from redirections) to Trident's list
  1566. CPrivacyRecord *pPrivacyRecord = _privacyQueue.Dequeue();
  1567. if (pPrivacyRecord)
  1568. {
  1569. while (pPrivacyRecord)
  1570. {
  1571. pPrivacyRecord->_dwPrivacyFlags |= dwTopLevelFlag;
  1572. pPrivacyServices->AddPrivacyInfoToList( pPrivacyRecord->_pszUrl, pPrivacyRecord->_pszPolicyRefUrl, pPrivacyRecord->_pszP3PHeader,
  1573. 0, pPrivacyRecord->_dwPrivacyFlags);
  1574. delete pPrivacyRecord;
  1575. // Add the dummy marker separating top level records if this is top level
  1576. if (dwTopLevelFlag)
  1577. pPrivacyServices->AddPrivacyInfoToList( TEXT(""), NULL, NULL, 0, PRIVACY_URLISTOPLEVEL);
  1578. pPrivacyRecord = _privacyQueue.Dequeue();
  1579. }
  1580. // Add the last one redirected url from the class itself since this was not added to the list
  1581. _dwPrivacyFlags |= dwTopLevelFlag;
  1582. pPrivacyServices->AddPrivacyInfoToList(_pszRedirectedURL, _pszPolicyRefURL, _pszP3PHeader, 0, _dwPrivacyFlags);
  1583. }
  1584. else
  1585. {
  1586. TCHAR szUrl[MAX_URL_STRING];
  1587. szUrl[0] = TEXT('\0');
  1588. // Get the url used for binding
  1589. if (pdoh->_pidl)
  1590. {
  1591. hRes = IEGetDisplayName(pdoh->_pidl, szUrl, SHGDN_FORPARSING);
  1592. }
  1593. else
  1594. {
  1595. LPOLESTR pwUrl = NULL;
  1596. hRes = pdoh->_GetCurrentPageW(&pwUrl, TRUE);
  1597. if (SUCCEEDED(hRes))
  1598. {
  1599. StrCpyN(szUrl, pwUrl, MAX_URL_STRING);
  1600. OleFree(pwUrl);
  1601. }
  1602. }
  1603. if (SUCCEEDED(hRes))
  1604. {
  1605. _dwPrivacyFlags |= dwTopLevelFlag;
  1606. pPrivacyServices->AddPrivacyInfoToList(szUrl, _pszPolicyRefURL, _pszP3PHeader, 0, _dwPrivacyFlags);
  1607. }
  1608. }
  1609. pPrivacyServices->Release();
  1610. }
  1611. }
  1612. #ifndef NO_DELEGATION
  1613. if (_pbscChained)
  1614. {
  1615. _pbscChained->OnObjectAvailable(riid, punk);
  1616. }
  1617. #endif
  1618. return S_OK;
  1619. }
  1620. HRESULT CDocObjectHost::CDOHBindStatusCallback::OnLowResource(DWORD reserved)
  1621. {
  1622. BSCMSG(TEXT("OnLowResource"), 0, 0);
  1623. #ifndef NO_DELEGATION
  1624. if (_pbscChained) {
  1625. _pbscChained->OnLowResource(reserved);
  1626. }
  1627. #endif
  1628. return S_OK;
  1629. }
  1630. HRESULT CDocObjectHost::CDOHBindStatusCallback::BeginningTransaction(LPCWSTR szURL, LPCWSTR szHeaders,
  1631. DWORD dwReserved, LPWSTR __RPC_FAR * ppwzAdditionalHeaders)
  1632. {
  1633. HRESULT hres;
  1634. #ifndef NO_DELEGATION
  1635. if (_pnegotiateChained) {
  1636. hres = _pnegotiateChained->BeginningTransaction(szURL, szHeaders, dwReserved, ppwzAdditionalHeaders);
  1637. }
  1638. else
  1639. {
  1640. #endif
  1641. // Here we pass headers to URLMon
  1642. hres=BuildAdditionalHeaders((LPCTSTR) _pszHeaders,(LPCWSTR *) ppwzAdditionalHeaders);
  1643. #ifndef NO_DELEGATION
  1644. }
  1645. #endif
  1646. return hres;
  1647. }
  1648. const WCHAR g_wszPicsLabel[] = L"\r\nPICS-Label:";
  1649. HRESULT CDocObjectHost::CDOHBindStatusCallback::OnResponse(DWORD dwResponseCode, LPCWSTR szResponseHeaders,
  1650. LPCWSTR szRequestHeaders,
  1651. LPWSTR *pszAdditionalRequestHeaders)
  1652. {
  1653. #ifndef NO_DELEGATION
  1654. if (_pnegotiateChained) {
  1655. _pnegotiateChained->OnResponse(dwResponseCode, szResponseHeaders, szRequestHeaders, pszAdditionalRequestHeaders);
  1656. }
  1657. else
  1658. {
  1659. #endif
  1660. #ifndef NO_DELEGATION
  1661. }
  1662. #endif
  1663. #ifdef FEATURE_PICS
  1664. /* CODEWORK: For next release, all response headers should be handled
  1665. * generically through _OnHttpEquiv, and rating labels should be
  1666. * processed there instead of through a private IOleCommandTarget
  1667. * interface with Trident.
  1668. */
  1669. /* NOTE: We still need to check for the PICS label header here, even
  1670. * if we chained to Trident or whoever above.
  1671. */
  1672. // (jbeda) this _dwPicsLabelSource stuff looks really screwy...
  1673. CDocObjectHost* pdoh = IToClass(CDocObjectHost, _bsc, this);
  1674. if (pdoh->_PicsProcBase._fbPicsWaitFlags & PICS_WAIT_FOR_INDOC) {
  1675. LPCWSTR pwszPicsLabel = StrStrW(szResponseHeaders, g_wszPicsLabel);
  1676. if (pwszPicsLabel != NULL) {
  1677. pdoh->_PicsProcBase._dwPicsLabelSource=PICS_LABEL_FROM_HEADER;
  1678. pwszPicsLabel += ARRAYSIZE(g_wszPicsLabel); /* skip \r\n and label name */
  1679. LPCWSTR pwszPicsLabelEnd = StrChrW(pwszPicsLabel, L'\r');
  1680. if (pwszPicsLabelEnd == NULL) {
  1681. // NOTE: lstrlenW doesn't work on Win95, so we do this manually.
  1682. for (pwszPicsLabelEnd = pwszPicsLabel;
  1683. *pwszPicsLabelEnd;
  1684. pwszPicsLabelEnd++)
  1685. ;
  1686. }
  1687. if (pwszPicsLabel && (pwszPicsLabelEnd > pwszPicsLabel))
  1688. {
  1689. WCHAR* pszLabel = new WCHAR[((int)(pwszPicsLabelEnd - pwszPicsLabel)) + 1];
  1690. if (pszLabel)
  1691. {
  1692. //
  1693. // pwszPicsLabel may not be NULL terminated so use memcpy to
  1694. // move it. Memory allocated by new is zero filled so
  1695. // pszLabel doesn't have to have L'\0' appeneded.
  1696. //
  1697. memcpy(pszLabel, pwszPicsLabel,
  1698. ((int)(pwszPicsLabelEnd - pwszPicsLabel)) * sizeof(WCHAR));
  1699. pdoh->_PicsProcBase._HandleInDocumentLabel(pszLabel);
  1700. delete pszLabel;
  1701. }
  1702. }
  1703. }
  1704. else
  1705. {
  1706. pdoh->_PicsProcBase._dwPicsLabelSource=PICS_LABEL_FROM_PAGE;
  1707. }
  1708. }
  1709. #endif
  1710. return S_OK;
  1711. }
  1712. HRESULT CDocObjectHost::CDOHBindStatusCallback::GetWindow(REFGUID rguidReason, HWND* phwnd)
  1713. {
  1714. CDocObjectHost* pdoh = IToClass(CDocObjectHost, _bsc, this);
  1715. if (!phwnd)
  1716. return E_POINTER;
  1717. if (pdoh->_psb) {
  1718. pdoh->_psb->GetWindow(phwnd);
  1719. } else {
  1720. *phwnd = pdoh->_hwnd;
  1721. }
  1722. return S_OK;
  1723. }
  1724. HRESULT CDocObjectHost::CDOHBindStatusCallback::OnSecurityProblem(DWORD dwProblem)
  1725. {
  1726. // force UI - return S_FALSE for all problems
  1727. return S_FALSE;
  1728. }
  1729. HRESULT CDocObjectHost::CDOHBindStatusCallback::_HandleSelfAssociate(void)
  1730. {
  1731. CDocObjectHost* pdoh = IToClass(CDocObjectHost, _bsc, this);
  1732. HRESULT hres;
  1733. IPersistMoniker* ppmk;
  1734. hres = pdoh->_CoCreateHTMLDocument(IID_IPersistMoniker, (LPVOID*)&ppmk);
  1735. if (SUCCEEDED(hres)) {
  1736. BIND_OPTS bindopts;
  1737. bindopts.cbStruct = sizeof(BIND_OPTS);
  1738. hres = _pbc->GetBindOptions(&bindopts);
  1739. if (SUCCEEDED(hres)) {
  1740. hres = ppmk->Load(FALSE, pdoh->_pmkCur, _pbc, bindopts.grfMode);
  1741. if (SUCCEEDED(hres)) {
  1742. ASSERT(NULL==pdoh->_pole);
  1743. hres = ppmk->QueryInterface(IID_IOleObject, (LPVOID*)&pdoh->_pole);
  1744. if (SUCCEEDED(hres)) {
  1745. pdoh->_InitOleObject();
  1746. TraceMsg(DM_SELFASC, "DOH::_HandleSelfAssociate self-association is working");
  1747. pdoh->_Navigate();
  1748. pdoh->_SetUpTransitionCapability();
  1749. _UpdateSSLIcon();
  1750. } else {
  1751. TraceMsg(DM_WARNING, "DOH::_HandleSelfAssociate ppmk->QI(IOleObject) failed (%x)", hres);
  1752. }
  1753. } else {
  1754. TraceMsg(DM_WARNING, "DOH::_HandleSelfAssociate ppmk->Load failed (%x)", hres);
  1755. }
  1756. } else {
  1757. TraceMsg(DM_WARNING, "DOH::_HandleSelfAssociate _pbc->GetBindOptions failed (%x)", hres);
  1758. }
  1759. ppmk->Release();
  1760. } else {
  1761. TraceMsg(DM_WARNING, "DOH::_HandleSelfAssociate CoCreateInst failed (%x)", hres);
  1762. }
  1763. return hres;
  1764. }
  1765. #define BUG_EXEC_ON_FAILURE //nash:31526
  1766. HRESULT CDocObjectHost::CDOHBindStatusCallback::OnStopBinding(HRESULT hrError,
  1767. LPCWSTR szError)
  1768. {
  1769. BSCMSG(TEXT("OnStopBinding"), this, hrError);
  1770. _fBinding = FALSE;
  1771. CDocObjectHost * pdoh = IToClass(CDocObjectHost, _bsc, this);
  1772. LPWSTR pwzHeaders = NULL;
  1773. BOOL fShouldDisplayError = TRUE;
  1774. DWORD dwStatusCode = 0; // We use 0 to mean no status yet
  1775. DWORD dwStatusCodeSize = sizeof(dwStatusCode);
  1776. BOOL bSuppressUI = FALSE;
  1777. BOOL fAsyncDownload = FALSE;
  1778. BOOL fAborted = _fAborted;
  1779. BOOL fCancelAutoSearch = FALSE;
  1780. BOOL fNavigateErrorFired = FALSE; // I cannot tell if _HandleHttpErrors are really mutually exclusive from the AutoSearching.
  1781. // Therefore I am adding a flag to make sure we don't fire NavigateError twice.
  1782. _fAborted = FALSE;
  1783. _privacyQueue.Reset();
  1784. ResetPrivacyInfo();
  1785. //
  1786. // this is to protect against urlmons behavior of returning
  1787. // an async error and sync error on the same call.
  1788. if (pdoh->_fSyncBindToObject && FAILED(hrError))
  1789. {
  1790. pdoh->_hrOnStopBinding = hrError;
  1791. return S_OK;
  1792. }
  1793. // if aborting to let Document.Write work...pretend everything is cool
  1794. if (_fDocWriteAbort && hrError == E_ABORT) hrError = S_OK;
  1795. // Why not use the cached value?
  1796. // pdoh->_GetOfflineSilent(0, &bSuppressUI);
  1797. bSuppressUI = (_bFrameIsSilent || _IsDesktopItem(pdoh)) ? TRUE : FALSE;
  1798. _bindst = 0; // go back to the normal state
  1799. if (_pbc && pdoh->_punkPending)
  1800. {
  1801. _pbc->RevokeObjectParam(L"__PrecreatedObject");
  1802. }
  1803. if (!_pbc)
  1804. {
  1805. ASSERT(0);
  1806. return S_OK;
  1807. }
  1808. // NOTES: Guard against last Release by _RevokeObjectParam
  1809. AddRef();
  1810. if (pdoh->_pwb)
  1811. {
  1812. pdoh->_pwb->SetNavigateState(BNS_NORMAL);
  1813. }
  1814. if (pdoh->_psb)
  1815. { // paranoia
  1816. pdoh->_psb->SetStatusTextSB(NULL);
  1817. }
  1818. BSCMSG("OnStopBinding calling _RevokeObjectParam", this, _pbc);
  1819. _RevokeObjectParam(_pbc);
  1820. _pbc->RevokeObjectParam(WSZGUID_OPID_DocObjClientSite);
  1821. //
  1822. // If the error code is a mapped error code (by URLMON), get the
  1823. // real error code from IBinding for display purpose.
  1824. //
  1825. HRESULT hrDisplay = hrError; // assume they are the same
  1826. #define ENABLE_WHEN_GETBINDRESULT_STARTS_WORKING
  1827. #ifdef ENABLE_WHEN_GETBINDRESULT_STARTS_WORKING
  1828. if (hrError>=INET_E_ERROR_FIRST && hrError<=INET_E_ERROR_LAST)
  1829. {
  1830. //
  1831. // We come here when _pib==NULL, if URLMON synchronously fails
  1832. // (such as a bad protocol).
  1833. //
  1834. // ASSERT(_pib);
  1835. //
  1836. if (_pib)
  1837. {
  1838. CLSID clsid;
  1839. LPWSTR pwszError = NULL;
  1840. HRESULT hresT=_pib->GetBindResult(&clsid, (DWORD *)&hrDisplay, &pwszError, NULL);
  1841. TraceMsg(TF_SHDBINDING, "DOH::OnStopBinding called GetBindResult %x->%x (%x)", hrError, hrDisplay, hresT);
  1842. if (SUCCEEDED(hresT))
  1843. {
  1844. //
  1845. // URLMON returns a native Win32 error.
  1846. //
  1847. if (hrDisplay && SUCCEEDED(hrDisplay))
  1848. {
  1849. hrDisplay = HRESULT_FROM_WIN32(hrDisplay);
  1850. }
  1851. //
  1852. // URLMON is not supposed to return 0 as the error code,
  1853. // which causes a "successfully done" error msgbox.
  1854. //
  1855. AssertMsg(hrDisplay != S_OK, TEXT("Call JohannP if you see this assert."));
  1856. if (pwszError)
  1857. {
  1858. OleFree(pwszError);
  1859. }
  1860. }
  1861. }
  1862. }
  1863. #endif
  1864. TraceMsg(TF_SHDBINDING, "DOH::BSC::OnStopBinding binding failed %x (hrDisplay=%x)", hrError, hrDisplay);
  1865. //
  1866. // HACK: If the object is associated with IE/Shell itself, but has
  1867. // no CLSID, we'll force MSHTML.
  1868. //
  1869. // if (_fSelfAssociated && (hrError==MK_E_INVALIDEXTENSION || hrError==REGDB_E_CLASSNOTREG)) {
  1870. // hrError = _HandleSelfAssociate();
  1871. // }
  1872. if (_pib)
  1873. {
  1874. // we dont need to do the expiry stuff here anymore.
  1875. // now mshtml should be doing it through the IPersistHistory
  1876. // get the expire info
  1877. // The HTTP rules for expiration are
  1878. // Expires: 0 expire immediately
  1879. // if Expires: <= Date: expire immediately
  1880. // if Expires: bad format expire immediately
  1881. IWinInetHttpInfo * phi;
  1882. if (SUCCEEDED(_pib->QueryInterface(IID_IWinInetHttpInfo, (LPVOID*)&phi)))
  1883. {
  1884. BYTE abBuffer[256]; // We don't care about this data, just
  1885. DWORD cbBuffer=sizeof(abBuffer); // whether it exists or not
  1886. if (phi->QueryInfo(HTTP_QUERY_LAST_MODIFIED, &abBuffer, &cbBuffer, NULL, 0) == S_OK)
  1887. pdoh->_fhasLastModified = TRUE;
  1888. if (phi->QueryInfo(HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER, &dwStatusCode, &dwStatusCodeSize, NULL, 0) != S_OK)
  1889. {
  1890. dwStatusCode = 0; // failed to get status code
  1891. dwStatusCodeSize = 0; // failed to get status code
  1892. }
  1893. // This code will decide if we should display a popup error;
  1894. // essentially, it detects if we can reasonably assume that
  1895. // HTML was returned in the error case; if so, we believe that
  1896. // it is an error page, so we let that display rather than a
  1897. // popup.
  1898. if (dwStatusCode)
  1899. {
  1900. // We got a status code; let's see if we have a
  1901. // content-type.
  1902. // HTTP retcode 204 is a "succeeded, do nothing" retcode
  1903. // So we should always suppress the popup; further, it is
  1904. // spec'd to NEVER have content, so we do this before checking
  1905. // for content-type.
  1906. // So is 100
  1907. // 100 is not in wininet.h
  1908. if (dwStatusCode == HTTP_STATUS_NO_CONTENT)
  1909. fShouldDisplayError = FALSE;
  1910. // what is max header size?
  1911. CHAR szContentType[1024];
  1912. DWORD dwContentTypeSize = sizeof(szContentType);
  1913. // This code handles a bug in URLMON where it tells us
  1914. // INET_E_DATA_NOT_AVAILABLE when in fact the
  1915. // data _was_ available. We don't want any future
  1916. // errors affected by this, so we restrict this
  1917. // hack to less than 600, and ONLY for the
  1918. // INET_E_DATA_NOT_AVAILABLE case.
  1919. if (hrError == INET_E_DATA_NOT_AVAILABLE &&
  1920. dwStatusCode < 600 &&
  1921. phi->QueryInfo(HTTP_QUERY_CONTENT_TYPE, &szContentType,
  1922. &dwContentTypeSize, NULL, 0) == S_OK)
  1923. {
  1924. fShouldDisplayError = FALSE;
  1925. }
  1926. //
  1927. // Handle http errors.
  1928. //
  1929. // Let's wrap the firing in case it is not the first attempt in future
  1930. if (dwStatusCode >= 400 && dwStatusCode <= 599)
  1931. {
  1932. if (!fNavigateErrorFired)
  1933. {
  1934. pdoh->_FireNavigateErrorHelper(NULL, dwStatusCode, &fCancelAutoSearch);
  1935. fNavigateErrorFired = TRUE;
  1936. }
  1937. if (!fCancelAutoSearch)
  1938. {
  1939. _HandleHttpErrors(dwStatusCode, _cbContentLength, pdoh);
  1940. }
  1941. else if (!pdoh->_fCanceledByBrowser)
  1942. {
  1943. pdoh->_CancelPendingNavigation(FALSE, FALSE);
  1944. }
  1945. }
  1946. }
  1947. phi->Release();
  1948. }
  1949. ATOMICRELEASE(_pib);
  1950. }
  1951. ATOMICRELEASE(_psvPrev);
  1952. //
  1953. // If the object does not support IOleObject, treat it as if we failed
  1954. // to bind.
  1955. //
  1956. if (_fBoundToNoOleObject)
  1957. {
  1958. ASSERT(SUCCEEDED(hrError));
  1959. hrError = MK_E_INVALIDEXTENSION;
  1960. }
  1961. // need to handle navigation in successful proxy response but w/
  1962. // 404 error. tonyci 13nov96. for autosearching & autosuffixing
  1963. if (FAILED(hrError))
  1964. {
  1965. BOOL fAddToMRU = FALSE;
  1966. pdoh->_fDrawBackground = TRUE;
  1967. TCHAR szURL[MAX_URL_STRING+1];
  1968. szURL[0] = TEXT('\0');
  1969. //
  1970. // It seems that in some of the case of hrError the code counts on dwStatusCode being set
  1971. // dwStatus is set exactly when the real error code was obtained from IBinding for display purpose
  1972. // For the other case I am going to use hrError
  1973. //
  1974. if (!fNavigateErrorFired)
  1975. {
  1976. if (dwStatusCode)
  1977. {
  1978. pdoh->_FireNavigateErrorHelper(NULL, dwStatusCode, &fCancelAutoSearch);
  1979. fNavigateErrorFired = TRUE;
  1980. }
  1981. else if (hrError>=INET_E_ERROR_FIRST && hrError<=INET_E_ERROR_LAST)
  1982. {
  1983. pdoh->_FireNavigateErrorHelper(NULL, hrError, &fCancelAutoSearch);
  1984. fNavigateErrorFired = TRUE;
  1985. }
  1986. }
  1987. if (pdoh->_pmkCur)
  1988. {
  1989. pdoh->_GetCurrentPage(szURL,ARRAYSIZE(szURL));
  1990. }
  1991. TraceMsg(TF_SHDBINDING, "DOH::OnStopBinding hrError=%x", hrError);
  1992. pdoh->_OnSetProgressPos(0, PROGRESS_RESET);
  1993. switch(hrError)
  1994. {
  1995. //
  1996. // If pmk->BindToObject is failed because of "binding", we should
  1997. // offer an option to download it as a file.
  1998. //
  1999. #ifdef BUG_EXEC_ON_FAILURE
  2000. case INET_E_CANNOT_INSTANTIATE_OBJECT:
  2001. TraceMsg(TF_SHDBINDING, "DOH::OnStopBinding IDS_ERR_OLESVR");
  2002. _SetSearchInfo(pdoh, 0, FALSE, FALSE, FALSE); // reset info
  2003. goto Lexec;
  2004. case INET_E_CANNOT_LOAD_DATA:
  2005. TraceMsg(TF_SHDBINDING, "DOH::OnStopBinding IDS_ERR_LOAD");
  2006. _SetSearchInfo(pdoh, 0, FALSE, FALSE, FALSE); // reset info
  2007. goto Lexec;
  2008. #else
  2009. case INET_E_CANNOT_INSTANTIATE_OBJECT:
  2010. _SetSearchInfo(pdoh, 0, FALSE, FALSE, FALSE); // reset info
  2011. if (MLShellMessageBox(pdoh->_hwnd,
  2012. MAKEINTRESOURCE(IDS_ERR_OLESVR),
  2013. MAKEINTRESOURCE(IDS_TITLE),
  2014. MB_YESNO|MB_ICONERROR,
  2015. szURL) == IDYES)
  2016. {
  2017. IUnknown * punk;
  2018. HRESULT hresT = pdoh->QueryInterface(IID_IUnknown, (void**)&punk);
  2019. if(SUCCEEDED(hresT))
  2020. {
  2021. if (!fAborted)
  2022. {
  2023. CDownLoad_OpenUI(pdoh->_pmkCur, _pbc, FALSE, TRUE, NULL, NULL, NULL, NULL, NULL, _pszRedirectedURL, pdoh->_uiCP, punk);
  2024. }
  2025. punk->Release();
  2026. }
  2027. }
  2028. break;
  2029. case INET_E_CANNOT_LOAD_DATA:
  2030. _SetSearchInfo(pdoh, 0, FALSE, FALSE, FALSE); // reset info
  2031. // e.g. click on .xls link when doc already open/modified/locked
  2032. // and say 'cancel'
  2033. //
  2034. if (MLShellMessageBox(pdoh->_hwnd,
  2035. MAKEINTRESOURCE(IDS_ERR_LOAD),
  2036. MAKEINTRESOURCE(IDS_TITLE),
  2037. MB_YESNO|MB_ICONERROR,
  2038. szURL) == IDYES)
  2039. {
  2040. IUnknown *punk;
  2041. HRESULT hresT = pdoh->QueryInterface(IID_IUnknown, (void**)&punk);
  2042. if(SUCCEEDED(hresT))
  2043. {
  2044. if (!fAborted)
  2045. {
  2046. CDownLoad_OpenUI(pdoh->_pmkCur, _pbc, FALSE, TRUE, NULL, NULL, NULL, NULL, _pszRedirectedURL, pdoh->_uiCP, punk);
  2047. }
  2048. punk->Release();
  2049. }
  2050. }
  2051. break;
  2052. #endif
  2053. //
  2054. // NOTES: According to JohannP, URLMON will give us
  2055. // REGDB_E_CLASSNOTREG. I'll leave MK_E_INVALIDEXTENSION
  2056. // to be compatible with old URLMON (which is harmless).
  2057. //
  2058. case MK_E_INVALIDEXTENSION:
  2059. case REGDB_E_CLASSNOTREG:
  2060. _SetSearchInfo(pdoh, 0, FALSE, FALSE, FALSE); // reset info
  2061. #ifdef BUG_EXEC_ON_FAILURE
  2062. Lexec: // nash:31526
  2063. // for various instantiation errors:
  2064. // - for ie3 we suppress messages and force a ShellExec as a
  2065. // 2nd try, pretty much always
  2066. // - for ie4 we should be more selective (nash:31526)
  2067. #endif
  2068. #ifdef FEATURE_PICS
  2069. // For data types that don't have a CLSID, we never get a chance
  2070. // to block in the CLASSIDAVAILABLE OnProgress notification, so
  2071. // we have to block here. However, avoid blocking documents such
  2072. // as HTML which we want to download completely so we can get
  2073. // ratings strings out of them.
  2074. //
  2075. if (!pdoh->_fPicsBlockLate && (pdoh->_PicsProcBase._fbPicsWaitFlags || !pdoh->_PicsProcBase._fPicsAccessAllowed))
  2076. {
  2077. pdoh->_PicsProcBase._fbPicsWaitFlags &= ~(PICS_WAIT_FOR_INDOC | PICS_WAIT_FOR_END); /* make sure we don't expect indoc ratings */
  2078. TraceMsg(DM_PICS, "OnStopBinding calling _PicsBlockingDialog, waitflags now %x", (DWORD)pdoh->_PicsProcBase._fbPicsWaitFlags);
  2079. if (pdoh->_PicsProcBase._PicsBlockingDialog() != IDOK)
  2080. {
  2081. TraceMsg(DM_PICS, "OnStopBinding, PICS canceled, calling _CancelPendingNavigation");
  2082. pdoh->_CancelPendingNavigation(FALSE);
  2083. break;
  2084. }
  2085. }
  2086. #endif
  2087. BeginningTransaction (NULL, NULL, 0, &pwzHeaders);
  2088. if (_dwBindVerb==BINDVERB_POST)
  2089. {
  2090. // This is a POST. Do it use the same moniker (modeless)
  2091. //
  2092. // Notes: The ownership of the data in pbinfo will be transfered
  2093. // to CDownLoad_OpenUIPost. Therefore, we should not call
  2094. // ReleaseBindInfo(pbinfo) here.
  2095. //
  2096. DWORD grfBINDF;
  2097. // The BINDINFO can not be on the stack since it will be freed by the
  2098. // download thread.
  2099. //
  2100. BINDINFO * pbinfo = (BINDINFO*)LocalAlloc(LPTR, SIZEOF(BINDINFO));
  2101. if (!pbinfo)
  2102. {
  2103. return E_OUTOFMEMORY;
  2104. }
  2105. pbinfo->cbSize = SIZEOF(BINDINFO);
  2106. GetBindInfo(&grfBINDF, pbinfo);
  2107. // If our POST was really a redirected POST, it will have
  2108. // turned into a GET. In this case, we need to release
  2109. // ownership of the data and pretend like the whole thing
  2110. // was a GET to start with.
  2111. if (pbinfo->dwBindVerb==BINDVERB_GET)
  2112. {
  2113. WCHAR wszUrl[INTERNET_MAX_URL_LENGTH];
  2114. ASSERT(_pszRedirectedURL);
  2115. SHTCharToUnicode(_pszRedirectedURL, wszUrl, ARRAYSIZE(wszUrl));
  2116. IUnknown * punk;
  2117. HRESULT hresT = pdoh->QueryInterface(IID_IUnknown, (void**)&punk);
  2118. if (SUCCEEDED(hresT))
  2119. {
  2120. VARIANT varOut = {0};
  2121. pdoh->_pmsoctBrowser->Exec(&CGID_ShellDocView, SHDVID_FIREFILEDOWNLOAD,
  2122. 0, NULL, &varOut);
  2123. if (V_VT(&varOut) != VT_BOOL || V_BOOL(&varOut) == VARIANT_FALSE)
  2124. {
  2125. if (!fAborted)
  2126. {
  2127. CDownLoad_OpenUIURL(wszUrl, NULL, pwzHeaders,
  2128. FALSE /* fSync */, FALSE /* fSaveAs */, pdoh->_fCalledMayOpenSafeDlg,
  2129. NULL, NULL, NULL, _pszRedirectedURL, pdoh->_uiCP, punk);
  2130. pwzHeaders = NULL; // ownership is to CDownload now
  2131. }
  2132. }
  2133. punk->Release();
  2134. }
  2135. ReleaseBindInfo(pbinfo); // This one is OK since we did not pass the pbinfo
  2136. LocalFree(pbinfo); // and we can free it
  2137. pbinfo = NULL;
  2138. }
  2139. else
  2140. {
  2141. ASSERT(pbinfo->dwBindVerb==BINDVERB_POST);
  2142. // Collect the headers associated with this xact
  2143. IUnknown * punk;
  2144. HRESULT hresT = pdoh->QueryInterface(IID_IUnknown, (void**)&punk);
  2145. if (SUCCEEDED(hresT))
  2146. {
  2147. VARIANT varOut = {0};
  2148. pdoh->_pmsoctBrowser->Exec(&CGID_ShellDocView, SHDVID_FIREFILEDOWNLOAD,
  2149. 0, NULL, &varOut);
  2150. if (V_VT(&varOut) != VT_BOOL || V_BOOL(&varOut) == VARIANT_FALSE)
  2151. {
  2152. if (!fAborted)
  2153. {
  2154. CDownLoad_OpenUI(pdoh->_pmkCur, _pbc, FALSE /* fSync */, FALSE /* fSaveAs */, pdoh->_fCalledMayOpenSafeDlg /* fSafe */, pwzHeaders, BINDVERB_POST, grfBINDF, pbinfo, _pszRedirectedURL, pdoh->_uiCP, punk);
  2155. pwzHeaders = NULL; // ownership is to CDownload now
  2156. }
  2157. }
  2158. punk->Release();
  2159. }
  2160. TraceMsg(TF_SHDBINDING, "DOH::OnStopBinding just called CDownLoad_OpenUIPost");
  2161. // NOTE: t-gpease 8-18-97
  2162. // Do not ReleaseBindInfo(pinfo) because it is used by the download thread.
  2163. // The thread is responsible for releasing it.
  2164. }
  2165. }
  2166. else
  2167. {
  2168. // Otherwise, spawn another thread and get it there.
  2169. // NOTE: If UnBind gets called then pdoh->_pmkCur will be NULL
  2170. // and URLMON is most likely returning a bogus error code. So
  2171. // we'll check the pointer and prevent from blowing up.
  2172. if (pdoh->_pmkCur)
  2173. {
  2174. BOOL fSafe = pdoh->_fCalledMayOpenSafeDlg;
  2175. IBrowserService * pbs;
  2176. if (PathIsFilePath(szURL) &&
  2177. SUCCEEDED(pdoh->QueryService(SID_STopFrameBrowser, IID_IBrowserService, (LPVOID *)&pbs)))
  2178. {
  2179. DWORD dwFlags;
  2180. if (SUCCEEDED(pbs->GetFlags(&dwFlags)) && (dwFlags & BSF_NOLOCALFILEWARNING))
  2181. {
  2182. fSafe = TRUE;
  2183. }
  2184. pbs->Release();
  2185. }
  2186. IUnknown *punk;
  2187. HRESULT hresT = pdoh->QueryInterface(IID_IUnknown, (void**)&punk);
  2188. if (SUCCEEDED(hresT))
  2189. {
  2190. VARIANT varOut = {0};
  2191. pdoh->_pmsoctBrowser->Exec(&CGID_ShellDocView, SHDVID_FIREFILEDOWNLOAD,
  2192. 0, NULL, &varOut);
  2193. if (V_VT(&varOut) != VT_BOOL || V_BOOL(&varOut) == VARIANT_FALSE)
  2194. {
  2195. if (pdoh->_pmsoctBrowser && pdoh->_fWindowOpen)
  2196. {
  2197. pdoh->_pmsoctBrowser->Exec(&CGID_Explorer, SBCMDID_CANCELANDCLOSE, 0, NULL, NULL);
  2198. }
  2199. if (!fAborted)
  2200. {
  2201. CDownLoad_OpenUI(pdoh->_pmkCur, pdoh->_pbcCur, FALSE, FALSE,
  2202. fSafe, pwzHeaders, NULL, pdoh->_bsc._dwBindf, NULL, _pszRedirectedURL,
  2203. pdoh->_uiCP, punk, pdoh->_fConfirmed);
  2204. pwzHeaders = NULL; // ownership is to CDownload now
  2205. }
  2206. }
  2207. punk->Release();
  2208. }
  2209. fAsyncDownload = TRUE;
  2210. }
  2211. }
  2212. if (pwzHeaders)
  2213. {
  2214. CoTaskMemFree(pwzHeaders);
  2215. }
  2216. break;
  2217. // URLMON failed to bind because it didn't know what to do with
  2218. // with this URL. Lets check and see if the Shell should handle
  2219. // it via a helper app (news:, mailto:, telnet:, etc.)
  2220. case INET_E_UNKNOWN_PROTOCOL:
  2221. _SetSearchInfo(pdoh, 0, FALSE, FALSE, FALSE); // reset info
  2222. {
  2223. // If we've been redirected, use that URL
  2224. //
  2225. if (_pszRedirectedURL)
  2226. {
  2227. StrCpyN(szURL, _pszRedirectedURL, ARRAYSIZE(szURL));
  2228. }
  2229. // Here we check to see if it is a URL we really want to shellexecute
  2230. // so it is handled by helper apps.....else it really is an error
  2231. if (ShouldShellExecURL(szURL))
  2232. {
  2233. // We can add this to the address bar MRU
  2234. fAddToMRU = TRUE;
  2235. // We need to decode this before passing it on to someone.
  2236. TCHAR szDecodedURL[INTERNET_MAX_URL_LENGTH];
  2237. DWORD cchDecodedURL = ARRAYSIZE(szDecodedURL);
  2238. // REVIEW: NT 319480 IE 54850 - need to append _pszLocation back to pszBadProtoURL...
  2239. //
  2240. // I assume the string was escaped when it came from urlmon, so we need
  2241. // to append it before PrepareURLForExternalApp.
  2242. //
  2243. // Note: if the url had been redirected above, _pszLocation has been updated
  2244. // to the new redirected URL, so we still want to append it.
  2245. //
  2246. if (pdoh->_pszLocation)
  2247. {
  2248. StrCatBuff(szURL, pdoh->_pszLocation, ARRAYSIZE(szURL));
  2249. }
  2250. PrepareURLForExternalApp(szURL, szDecodedURL, &cchDecodedURL);
  2251. // PathQuoteSpaces(szDecodedURL);
  2252. SHELLEXECUTEINFO sei = {0};
  2253. sei.cbSize = sizeof(sei);
  2254. sei.lpFile = szDecodedURL;
  2255. sei.nShow = SW_SHOWNORMAL;
  2256. if (!ShellExecuteEx(&sei))
  2257. {
  2258. if(!bSuppressUI)
  2259. {
  2260. IE_ErrorMsgBox(pdoh->_psb, pdoh->_hwnd, hrDisplay, szError,
  2261. szDecodedURL, IDS_CANTSHELLEX, MB_OK | MB_ICONSTOP );
  2262. }
  2263. }
  2264. //
  2265. // We want to close the browser window if this is the
  2266. // very first navigation.
  2267. //
  2268. fAsyncDownload = TRUE;
  2269. }
  2270. else if ((!bSuppressUI) && (!fCancelAutoSearch))
  2271. {
  2272. _NavigateToErrorPage(ERRORPAGE_SYNTAX, pdoh, FALSE);
  2273. }
  2274. break;
  2275. }
  2276. case E_ABORT:
  2277. case HRESULT_FROM_WIN32(ERROR_CANCELLED):
  2278. _SetSearchInfo(pdoh, 0, FALSE, FALSE, FALSE); // reset info
  2279. // If the binding was aborted or canceled and this is
  2280. // a navigation that was delegated from Trident, then
  2281. // we must fire the FileDownload event so Trident won't
  2282. // switch the markup.
  2283. //
  2284. if (pdoh->_fDelegatedNavigation && pdoh->_pmsoctBrowser)
  2285. {
  2286. VARIANT varOut = {0};
  2287. pdoh->_pmsoctBrowser->Exec(&CGID_ShellDocView, SHDVID_FIREFILEDOWNLOAD, 0, NULL, &varOut);
  2288. }
  2289. break;
  2290. #ifdef BUG_EXEC_ON_FAILURE
  2291. case E_NOINTERFACE: // nash:31526
  2292. TraceMsg(TF_SHDBINDING, "DOH::OnStopBinding E_NOINTERFACE");
  2293. goto Lexec;
  2294. #endif
  2295. case INET_E_RESOURCE_NOT_FOUND:
  2296. case INET_E_DATA_NOT_AVAILABLE:
  2297. if (!fCancelAutoSearch)
  2298. {
  2299. if (_HandleFailedNavigationSearch(&fShouldDisplayError, dwStatusCode, pdoh, hrDisplay, (LPTSTR) &szURL, szError, _pib) != S_OK)
  2300. {
  2301. fShouldDisplayError = TRUE;
  2302. }
  2303. }
  2304. else if (!pdoh->_fCanceledByBrowser)
  2305. {
  2306. pdoh->_CancelPendingNavigation(FALSE, FALSE);
  2307. }
  2308. // intentional fallthrough to default to popup if needed
  2309. case INET_E_DOWNLOAD_FAILURE:
  2310. if(IsGlobalOffline())
  2311. {
  2312. fShouldDisplayError = FALSE;
  2313. break;
  2314. }
  2315. // otherwise fall through to do default handling
  2316. default:
  2317. {
  2318. if (fShouldDisplayError)
  2319. {
  2320. _SetSearchInfo(pdoh, 0, FALSE, FALSE, FALSE); // reset info
  2321. if ((!bSuppressUI) && (!fCancelAutoSearch))
  2322. {
  2323. //
  2324. // If we're in a frame try to navigate in place. This
  2325. // won't work if we're in a synchronous call
  2326. // (_fSetTarget).
  2327. //
  2328. BOOL fNavigateInPlace = pdoh->_fHaveParentSite && !pdoh->_fSetTarget;
  2329. _NavigateToErrorPage(ERRORPAGE_DNS, pdoh, fNavigateInPlace);
  2330. }
  2331. }
  2332. }
  2333. break;
  2334. }
  2335. // Tell addressbar to not add this to its mru
  2336. if (!fAddToMRU)
  2337. {
  2338. _DontAddToMRU(pdoh);
  2339. }
  2340. //
  2341. // Prepare for the case where the container keep us visible
  2342. // after hitting this code (Explorer does, IE doesn't).
  2343. //
  2344. pdoh->_fDrawBackground = TRUE;
  2345. // In the case of quickly jumping to another link, we end up with
  2346. // a _hwnd being NULL and we were invalidating the desktop. So,
  2347. // I check for NULL here before calling InvalidateRect.
  2348. if (pdoh->_hwnd)
  2349. {
  2350. InvalidateRect(pdoh->_hwnd, NULL, TRUE);
  2351. }
  2352. // Tell the browser to cancel the pending navigation only
  2353. // if it has not been canceled by the browser itself.
  2354. // and if the navigation wasn't delegated from the document.
  2355. //
  2356. if (!pdoh->_fCanceledByBrowser)
  2357. {
  2358. pdoh->_CancelPendingNavigation(fAsyncDownload, FALSE, pdoh->_fDelegatedNavigation);
  2359. if (pdoh->_fDelegatedNavigation)
  2360. {
  2361. IDocNavigate * pDocNavigate;
  2362. HRESULT hr = E_FAIL;
  2363. if ( pdoh->_pwb )
  2364. {
  2365. hr = pdoh->_pwb->QueryInterface(IID_PPV_ARG(IDocNavigate, &pDocNavigate));
  2366. }
  2367. if (S_OK == hr)
  2368. {
  2369. pDocNavigate->OnReadyStateChange(NULL, READYSTATE_COMPLETE);
  2370. pDocNavigate->Release();
  2371. }
  2372. }
  2373. }
  2374. else
  2375. {
  2376. TraceMsg(TF_SHDNAVIGATE|TF_SHDPROGRESS,
  2377. "DOH::::OnStopBinding not calling _CancelPendingNav");
  2378. }
  2379. }
  2380. else
  2381. {
  2382. BOOL bDidNavigate = FALSE;
  2383. // Might have redirected to mailto: or some other protocol handled by
  2384. // plugable protocol that does some magic (eg launch mail program) and
  2385. // reports OnStopBinding w/o going through OnObjectAvailable!
  2386. if (NULL == pdoh->_pole && !pdoh->_fCanceledByBrowser)
  2387. {
  2388. pdoh->_CancelPendingNavigation(FALSE);
  2389. }
  2390. // It is still possible that our Proxy failed to find the server but
  2391. // gave us HTML. If this is the case, and the user has "find sites"
  2392. // set, we should go ahead and start trying to do our automatic
  2393. // navigation stuff.
  2394. if (dwStatusCode && DO_SEARCH_ON_STATUSCODE(dwStatusCode))
  2395. {
  2396. if (!fCancelAutoSearch)
  2397. {
  2398. if (_HandleFailedNavigationSearch(&fShouldDisplayError, dwStatusCode, pdoh, hrDisplay, NULL, szError, _pib) == S_OK)
  2399. {
  2400. bDidNavigate = TRUE;
  2401. }
  2402. }
  2403. else if (!pdoh->_fCanceledByBrowser)
  2404. {
  2405. pdoh->_CancelPendingNavigation(FALSE, FALSE);
  2406. }
  2407. // Note, since the Proxy will have given us HTML in this case,
  2408. // we will never display an error dialog.
  2409. }
  2410. if (!bDidNavigate && !pdoh->_fDocCanNavigate)
  2411. {
  2412. _SetSearchInfo(pdoh, 0, FALSE, FALSE, FALSE); // reset info
  2413. // We can suppress this redundant call to Add to History if DocObject
  2414. // is MSHTML, since it will report readystate
  2415. if (!_fBoundToMSHTML && pdoh->_pmkCur)
  2416. {
  2417. TCHAR szUrl[MAX_URL_STRING+1];
  2418. pdoh->_GetCurrentPage(szUrl,ARRAYSIZE(szUrl));
  2419. if (pdoh->_pszLocation)
  2420. {
  2421. StrCatBuff(szUrl, pdoh->_pszLocation, ARRAYSIZE(szUrl));
  2422. }
  2423. if (!bSuppressUI)
  2424. {
  2425. BOOL fWriteHistory = TRUE;
  2426. BOOL fSelectHistory = TRUE;
  2427. if (NULL != pdoh->_pocthf)
  2428. {
  2429. MSOCMD rgCmd[] = { { SBCMDID_WRITEHIST, 0 }, { SBCMDID_SELECTHISTPIDL, 0 } };
  2430. pdoh->_pocthf->QueryStatus(&CGID_Explorer, ARRAYSIZE(rgCmd), rgCmd, NULL);
  2431. fWriteHistory = BOOLIFY(rgCmd[0].cmdf & MSOCMDF_ENABLED);
  2432. fSelectHistory = BOOLIFY(rgCmd[1].cmdf & MSOCMDF_ENABLED);
  2433. }
  2434. AddUrlToUrlHistoryStg(szUrl,
  2435. NULL,
  2436. pdoh->_pwb,
  2437. fWriteHistory,
  2438. fSelectHistory ? pdoh->_pocthf : NULL,
  2439. pdoh->get_punkSFHistory(), NULL);
  2440. }
  2441. }
  2442. } // if !bDidNavigate
  2443. } // if failed(hrerror) ... else
  2444. // Released here because we may need it for OpenUI() w/ POST verb
  2445. ATOMICRELEASE(_pbc);
  2446. #ifndef NO_DELEGATION
  2447. if (_pbscChained)
  2448. {
  2449. CHAINMSG("OnStopBinding", hrError);
  2450. _pbscChained->OnStopBinding(hrError, szError);
  2451. }
  2452. #endif
  2453. ATOMICRELEASE(_pbscChained);
  2454. ATOMICRELEASE(_pnegotiateChained);
  2455. pdoh->_ResetStatusBar();
  2456. ATOMICRELEASE(pdoh->_pbcCur);
  2457. if (_pszHeaders)
  2458. {
  2459. LocalFree(_pszHeaders);
  2460. _pszHeaders = NULL;
  2461. }
  2462. if (_hszPostData)
  2463. {
  2464. GlobalFree(_hszPostData);
  2465. _hszPostData = NULL;
  2466. }
  2467. // NOTES: Guard against last Release by _RevokeObjectParam
  2468. Release();
  2469. return S_OK;
  2470. }
  2471. void CDocObjectHost::CDOHBindStatusCallback::AbortBinding(void)
  2472. {
  2473. TraceMsg(TF_SHDPROGRESS, "CDOH::CBSC::AbortBinding called _pib=%x", _pib);
  2474. if (_pib)
  2475. {
  2476. TraceMsg(0, "sdv TR AbortBinding Calling _pib->Abort");
  2477. //
  2478. // Notes: OnStopBinding(E_ABORT) will be called from _pib->Abort
  2479. //
  2480. HRESULT hresT = _pib->Abort();
  2481. TraceMsg(TF_SHDBINDING, "sdv TR AbortBinding Called _pib->Abort (%x)", hresT);
  2482. // URLMon may call our OnStopBinding asynchronously.
  2483. ATOMICRELEASE(_pib);
  2484. CDocObjectHost* pdoh = IToClass(CDocObjectHost, _bsc, this);
  2485. if(pdoh->_dwProgressPos)
  2486. {
  2487. pdoh->_ResetStatusBar();
  2488. pdoh->_OnSetProgressPos(0, PROGRESS_RESET);
  2489. }
  2490. }
  2491. }
  2492. //
  2493. // NavigatesToErrorPage cancels the pending navigation and and navigates to
  2494. // an internal error page.
  2495. //
  2496. void CDocObjectHost::CDOHBindStatusCallback::_NavigateToErrorPage(DWORD dwError, CDocObjectHost* pdoh, BOOL fInPlace)
  2497. {
  2498. ASSERT(IsErrorHandled(dwError));
  2499. ASSERT(pdoh);
  2500. // Security: Release the pre-created object because we don't want
  2501. // anyone to have access to the OM of the navigated error document
  2502. // if they obtained the reference before the error navigation.
  2503. // Releasing the reference prevents a parent window from getting keys
  2504. // to the My Computer zone.
  2505. pdoh->_ReleaseOleObject(FALSE);
  2506. pdoh->_ReleasePendingObject(FALSE);
  2507. //
  2508. // pdoh->_pmkCur can be NULL if this is a "DNS" error and Unbind has already
  2509. // been called.
  2510. //
  2511. if (pdoh->_pmkCur)
  2512. {
  2513. //
  2514. // Save the url the user attempted to navigate to. It will be used
  2515. // to refresh the page.
  2516. //
  2517. if (pdoh->_pwszRefreshUrl)
  2518. {
  2519. OleFree(pdoh->_pwszRefreshUrl);
  2520. pdoh->_pwszRefreshUrl = NULL;
  2521. }
  2522. pdoh->_pmkCur->GetDisplayName(pdoh->_pbcCur, NULL,
  2523. &pdoh->_pwszRefreshUrl);
  2524. }
  2525. if ((NULL == pdoh->_pwszRefreshUrl) || !IsErrorUrl(pdoh->_pwszRefreshUrl))
  2526. {
  2527. // Build the error page url.
  2528. //
  2529. TCHAR szErrorUrl[MAX_URL_STRING];
  2530. if (fInPlace)
  2531. {
  2532. HRESULT hr;
  2533. hr = MLBuildResURLWrap(TEXT("shdoclc.dll"),
  2534. HINST_THISDLL,
  2535. ML_CROSSCODEPAGE,
  2536. (TCHAR *)c_aErrorUrls[EUIndexFromError(dwError)].pszUrl,
  2537. szErrorUrl,
  2538. ARRAYSIZE(szErrorUrl),
  2539. TEXT("shdocvw.dll"));
  2540. if (SUCCEEDED(hr))
  2541. {
  2542. //
  2543. // Navigate to the error page.
  2544. //
  2545. IMoniker* pIMoniker;
  2546. if (SUCCEEDED(MonikerFromString(szErrorUrl, &pIMoniker)))
  2547. {
  2548. ASSERT(pIMoniker);
  2549. #ifdef DEBUG
  2550. pdoh->_fFriendlyError = TRUE;
  2551. #endif
  2552. pdoh->SetTarget(pIMoniker, pdoh->_uiCP, NULL, NULL, NULL, 0);
  2553. pIMoniker->Release();
  2554. }
  2555. }
  2556. }
  2557. else
  2558. {
  2559. const WCHAR* const pszFmt = L"#%s";
  2560. HRESULT hr;
  2561. hr = MLBuildResURLWrap(TEXT("shdoclc.dll"),
  2562. HINST_THISDLL,
  2563. ML_CROSSCODEPAGE,
  2564. (TCHAR *)c_aErrorUrls[EUIndexFromError(dwError)].pszUrl,
  2565. szErrorUrl,
  2566. ARRAYSIZE(szErrorUrl),
  2567. TEXT("shdocvw.dll"));
  2568. if (SUCCEEDED(hr))
  2569. {
  2570. int nLenWritten;
  2571. // append the #<refresh URL>
  2572. nLenWritten = lstrlen(szErrorUrl);
  2573. wnsprintf(szErrorUrl + nLenWritten,
  2574. ARRAYSIZE(szErrorUrl) - nLenWritten,
  2575. pszFmt,
  2576. pdoh->_pwszRefreshUrl ? pdoh->_pwszRefreshUrl : L"");
  2577. //
  2578. // Cancel the server page and display the internal page instead.
  2579. //
  2580. if (!pdoh->_fCanceledByBrowser)
  2581. pdoh->_CancelPendingNavigation(FALSE);
  2582. // Turn off the flag in the base browser that
  2583. // indicates that the view should be reused.
  2584. // We want a new view in this case.
  2585. //
  2586. if ( pdoh->_pwb )
  2587. {
  2588. pdoh->_pwb->SetFlags(NULL, BSF_HTMLNAVCANCELED);
  2589. }
  2590. pdoh->_DoAsyncNavigation(szErrorUrl);
  2591. pdoh->_fCanceledByBrowser = TRUE;
  2592. }
  2593. }
  2594. }
  2595. return;
  2596. }
  2597. //
  2598. // Check if the user turned off friendly http errors. Default is yes.
  2599. //
  2600. BOOL CDocObjectHost::CDOHBindStatusCallback::_DisplayFriendlyHttpErrors()
  2601. {
  2602. BOOL fRet;
  2603. DWORD dwType = REG_SZ;
  2604. TCHAR szYesOrNo[20];
  2605. DWORD cbSize = sizeof(szYesOrNo);
  2606. if (ERROR_SUCCESS == SHRegGetUSValue(REGSTR_PATH_MAIN,
  2607. REGSTR_VAL_HTTP_ERRORS, &dwType,
  2608. (LPVOID)szYesOrNo, &cbSize, FALSE,
  2609. NULL, 0))
  2610. {
  2611. fRet = StrCmpI(szYesOrNo, L"no");
  2612. }
  2613. else
  2614. {
  2615. fRet = TRUE;
  2616. }
  2617. return fRet;
  2618. }
  2619. //
  2620. // Error handler
  2621. //
  2622. void CDocObjectHost::CDOHBindStatusCallback::_HandleHttpErrors(DWORD dwError, DWORD cbContentLength, CDocObjectHost* pdoh)
  2623. {
  2624. // Tell addressbar to not add this to its mru
  2625. _DontAddToMRU(pdoh);
  2626. if (IsErrorHandled(dwError))
  2627. {
  2628. pdoh->_fErrorPage = TRUE;
  2629. //
  2630. // On a 4XX error display an internal page if the server returned a
  2631. // page smaller than the threshold value. If the page is larger than
  2632. // the threshold, display it.
  2633. //
  2634. // If the content length is zero assume the server didn't send the
  2635. // length. In this case take the conservative approach and don't
  2636. // show our page.
  2637. //
  2638. if (cbContentLength != 0 &&
  2639. cbContentLength <= _GetErrorThreshold(dwError))
  2640. {
  2641. if (_DisplayFriendlyHttpErrors())
  2642. _NavigateToErrorPage(dwError, pdoh, TRUE);
  2643. }
  2644. }
  2645. return;
  2646. }
  2647. //
  2648. // Informs the address bar to not put this page in its mru
  2649. //
  2650. void CDocObjectHost::CDOHBindStatusCallback::_DontAddToMRU(CDocObjectHost* pdoh)
  2651. {
  2652. IDockingWindow* pdw = NULL;
  2653. IOleCommandTarget* poct;
  2654. if (pdoh->_psp &&
  2655. SUCCEEDED(pdoh->_psp->QueryService(SID_SExplorerToolbar, IID_IDockingWindow, (LPVOID*)&pdw)))
  2656. {
  2657. if (SUCCEEDED(pdw->QueryInterface(IID_IOleCommandTarget, (LPVOID*)&poct)))
  2658. {
  2659. // Get the URL we were navigating to
  2660. LPWSTR pszUrl;
  2661. if (pdoh->_pmkCur &&
  2662. SUCCEEDED(pdoh->_pmkCur->GetDisplayName(pdoh->_pbcCur, NULL, &pszUrl)))
  2663. {
  2664. LBSTR::CString strDisplay( pszUrl );
  2665. VARIANT varURL = {0};
  2666. varURL.vt = VT_BSTR;
  2667. varURL.bstrVal = strDisplay;
  2668. poct->Exec(&CGID_Explorer, SBCMDID_ERRORPAGE, 0, &varURL, NULL);
  2669. OleFree(pszUrl);
  2670. }
  2671. poct->Release();
  2672. }
  2673. pdw->Release();
  2674. }
  2675. }
  2676. //
  2677. // Tells the addressbar that we are autosearching so that it can update
  2678. // the pending url in its mru
  2679. //
  2680. void CDocObjectHost::CDOHBindStatusCallback::_UpdateMRU(CDocObjectHost* pdoh, LPCWSTR pszUrl)
  2681. {
  2682. IDockingWindow* pdw = NULL;
  2683. IOleCommandTarget* poct;
  2684. if (pdoh->_psp &&
  2685. SUCCEEDED(pdoh->_psp->QueryService(SID_SExplorerToolbar, IID_IDockingWindow, (LPVOID*)&pdw)))
  2686. {
  2687. if (SUCCEEDED(pdw->QueryInterface(IID_IOleCommandTarget, (LPVOID*)&poct)))
  2688. {
  2689. // Copy url to stack allocated bstr
  2690. LBSTR::CString strDisplay( pszUrl );
  2691. VARIANT varURL = {0};
  2692. varURL.vt = VT_BSTR;
  2693. varURL.bstrVal = strDisplay;
  2694. poct->Exec(&CGID_Explorer, SBCMDID_AUTOSEARCHING, 0, &varURL, NULL);
  2695. poct->Release();
  2696. }
  2697. pdw->Release();
  2698. }
  2699. }
  2700. //
  2701. // S_OK means we successfully did a navigation
  2702. // S_FALSE means that we did everything ok, but did not navigate
  2703. // E_* means some internal api failed.
  2704. //
  2705. HRESULT CDocObjectHost::CDOHBindStatusCallback::_HandleFailedNavigationSearch(
  2706. LPBOOL pfShouldDisplayError,
  2707. DWORD dwStatusCode,
  2708. CDocObjectHost * pdoh,
  2709. HRESULT hrDisplay,
  2710. TCHAR * szURL,
  2711. LPCWSTR szError,
  2712. IBinding * pib,
  2713. BOOL fAddMRU, /* = TRUE */
  2714. BOOL fFromTrident /* = FALSE */)
  2715. {
  2716. DWORD dwSearchForExtensions = NO_SUFFIXES;
  2717. DWORD dwDo404Search = PROMPTSEARCH;
  2718. BOOL bAskUser = TRUE; // rely on init
  2719. BOOL bDoSearch = FALSE; // rely on init
  2720. HRESULT hres = S_FALSE;
  2721. BOOL bSuppressUI = FALSE;
  2722. BOOL bFrameIsOffline = FALSE;
  2723. BOOL bPrepareForSearch = FALSE;
  2724. DWORD dwSuffixIndex = 0;
  2725. BOOL bAllowSearch = FALSE;
  2726. BOOL bContinueSearch = FALSE;
  2727. BOOL bSentToEngine = FALSE;
  2728. BOOL bOnProxy = FALSE;
  2729. TCHAR szSearchFormatStr[MAX_SEARCH_FORMAT_STRING];
  2730. DWORD dwSearchStyle = 3; // "display search results and navigate to the most likely site"
  2731. ASSERT(pdoh);
  2732. #define SAFETRACE(psz) (psz ? psz : TEXT(""))
  2733. TraceMsg(TF_SHDNAVIGATE, "DOH::BSC::_HFNS() entered status = %d, url = %s, pib = %X", dwStatusCode, SAFETRACE(szURL) , pib);
  2734. if (FAILED(GetSearchKeys(pdoh->_psp, &dwSearchStyle, &dwSearchForExtensions, &dwDo404Search)))
  2735. {
  2736. return E_FAIL;
  2737. }
  2738. TraceMsg(TF_SHDNAVIGATE, "DOH::BSC::_HFNS() dwSearch = %d, do404 = %d", dwSearchForExtensions, dwDo404Search);
  2739. // Get any persistent information from the last request
  2740. VARIANT varURL = {0};
  2741. _GetSearchInfo(pdoh->_psp, &dwSuffixIndex, &bAllowSearch, &bContinueSearch, &bSentToEngine, &varURL);
  2742. // See if window.external.autoscan() was called
  2743. BOOL fAutoScan = (varURL.vt == VT_BSTR);
  2744. TraceMsg(TF_SHDNAVIGATE, "DOH::BSC::_HFNS() index = %d, allow = %d, cont = %d, sent = %d", dwSuffixIndex, bAllowSearch, bContinueSearch, bSentToEngine);
  2745. // Why not use the cached value?
  2746. // pdoh->_GetOfflineSilent(&bFrameIsOffline, &bSuppressUI);
  2747. bFrameIsOffline = _bFrameIsOffline ? TRUE : FALSE;
  2748. bSuppressUI = (_bFrameIsSilent || _IsDesktopItem(pdoh)) ? TRUE : FALSE;
  2749. // if we are at the end of the extension list, turn off extensions
  2750. BOOL fAutoSearching = FALSE;
  2751. if (dwSearchForExtensions)
  2752. {
  2753. if (dwSuffixIndex == 0 && dwSearchStyle != 0)
  2754. {
  2755. StrCpyN(szSearchFormatStr, L"? %s", ARRAYSIZE(szSearchFormatStr));
  2756. fAutoSearching = TRUE;
  2757. }
  2758. else if (GetSearchFormatString(dwSuffixIndex, szSearchFormatStr, sizeof(szSearchFormatStr)) != ERROR_SUCCESS)
  2759. {
  2760. dwSearchForExtensions = DONE_SUFFIXES;
  2761. StrCpyN(szSearchFormatStr, TEXT("%s"), ARRAYSIZE(szSearchFormatStr));
  2762. }
  2763. }
  2764. else
  2765. {
  2766. dwSearchForExtensions = DONE_SUFFIXES;
  2767. }
  2768. // don't try a 404 srch if we are still trying suffixes
  2769. if (dwSearchForExtensions == SCAN_SUFFIXES)
  2770. dwDo404Search = NEVERSEARCH;
  2771. {
  2772. DWORD dwOptions;
  2773. if (SUCCEEDED(_GetRequestFlagFromPIB(pib, &dwOptions)))
  2774. {
  2775. if (dwOptions & INTERNET_REQFLAG_VIA_PROXY)
  2776. {
  2777. bOnProxy = TRUE;
  2778. }
  2779. }
  2780. else
  2781. {
  2782. TraceMsg(TF_SHDNAVIGATE, "DOH::BSC::_HFNS() QI to IWinInetInfo failed");
  2783. }
  2784. }
  2785. TraceMsg(TF_SHDNAVIGATE, "DOH::BSC::_HFNS() search = %d, do404 = %d, onproxy = %d, szSearch = %s", dwSearchForExtensions, dwDo404Search, bOnProxy, SAFETRACE(szSearchFormatStr));
  2786. // Prepare to do an automatic search if the navigation failed
  2787. // and we think a search might be valuable.
  2788. // These cases are:
  2789. // (1) if the previous navigation was search-generated (bContinue)
  2790. // (2) the user allows searching (bAllow)
  2791. // (3) we are searching for extensions or autosearching
  2792. // (4) this is a status code we allow searching for
  2793. // (5) if over proxy, continue searching even on 404
  2794. // Note: 404 is special; it is the case that most servers return this if
  2795. // the documnet is not there, but Proxies also return this if the server
  2796. // was not found - a conditon which normally makes us search. This means
  2797. // that a 404 over proxy actually causes a search to occur, which is not
  2798. // what we want.
  2799. // Is there any way I can tell the difference?
  2800. bPrepareForSearch = ((bContinueSearch || (bAllowSearch)) &&
  2801. (fAutoScan || SHOULD_DO_SEARCH(dwSearchForExtensions, dwDo404Search)) &&
  2802. DO_SEARCH_ON_STATUSCODE(dwStatusCode) &&
  2803. (!bOnProxy || pdoh->_fDocCanNavigate || (dwStatusCode == HTTP_STATUS_NOT_FOUND)));
  2804. if (bPrepareForSearch)
  2805. {
  2806. TraceMsg(TF_SHDNAVIGATE, "DOH::BSC::_HFNS() Preparing for Search...");
  2807. HRESULT hr = S_OK;
  2808. // If we don't have the url we are searching, get it from the addressbar
  2809. if (!fAutoScan)
  2810. hr = _GetSearchString(pdoh->_psp, &varURL);
  2811. if (S_OK!=hr && pdoh->_fDocCanNavigate)
  2812. {
  2813. hr = VariantCopy(&varURL, &pdoh->_varUserEnteredUrl);
  2814. }
  2815. // If we have completed the autoscan, see if there is a special error page that
  2816. // we should display.
  2817. VARIANT varScanFailure = {0};
  2818. if (SUCCEEDED(hr) &&
  2819. dwSearchForExtensions == DONE_SUFFIXES &&
  2820. SUCCEEDED(_GetScanFailureUrl(pdoh->_psp, &varScanFailure)))
  2821. {
  2822. bDoSearch = TRUE;
  2823. }
  2824. else if (SUCCEEDED(hr) &&
  2825. (dwSearchForExtensions == SCAN_SUFFIXES || dwDo404Search == ALWAYSSEARCH))
  2826. {
  2827. bDoSearch = TRUE;
  2828. }
  2829. else
  2830. {
  2831. bDoSearch = FALSE;
  2832. }
  2833. bAskUser = FALSE;
  2834. TraceMsg(TF_SHDNAVIGATE, "DOH::BSC::_HFNS() typedurl = %s, ask = %d, dosearch = %d", varURL.bstrVal, bAskUser, bDoSearch);
  2835. // Don't prompt user if there is an extension, since we are going to
  2836. // not scan anyway.
  2837. if (bDoSearch)
  2838. {
  2839. PARSEDURL pu;
  2840. pu.cbSize = SIZEOF(PARSEDURL);
  2841. if (ParseURL(varURL.bstrVal, &pu) == URL_E_INVALID_SYNTAX)
  2842. {
  2843. // only if this is not a valid URL, should we try to do this searching
  2844. // but try to avoid the case of typos like http;//something.something.com
  2845. // The malformed URL case
  2846. if (!fAutoSearching &&
  2847. (//StrChrI(varURL.bstrVal, L'.') ||
  2848. StrChrI(varURL.bstrVal, L'/') ||
  2849. StrChrI(varURL.bstrVal, L' '))
  2850. )
  2851. {
  2852. bAskUser = FALSE;
  2853. bDoSearch = FALSE;
  2854. }
  2855. }
  2856. else
  2857. {
  2858. bAskUser = FALSE;
  2859. bDoSearch = FALSE;
  2860. }
  2861. }
  2862. TCHAR szT[MAX_URL_STRING + SEARCHPREFIXLENGTH];
  2863. DWORD cchT = SIZECHARS(szT);
  2864. // Bug 35354 has been resolved "not repro" because the dialog below
  2865. // currently cannot ever be displayed (there is no way for bAskUser to
  2866. // be true in the following conditional). If that changes, then that bug
  2867. // needs to get fixed.
  2868. if (bAskUser)
  2869. {
  2870. PrepareURLForDisplay(varURL.bstrVal, szT, &cchT);
  2871. // If we ask the user, make sure we don't display another
  2872. // error dialog.
  2873. *pfShouldDisplayError = FALSE;
  2874. // S_OK means we handled any popups; if we return an error,
  2875. // the caller may display an error dialog
  2876. hres = S_OK;
  2877. if (!bSuppressUI && IDYES == IE_ErrorMsgBox(NULL, pdoh->_hwnd, hrDisplay, szError, szT, IDS_CANTFINDURL, MB_YESNO|MB_ICONSTOP))
  2878. {
  2879. bDoSearch = TRUE;
  2880. }
  2881. else
  2882. {
  2883. _SetSearchInfo(pdoh, 0, FALSE, FALSE, FALSE); // reset info
  2884. bDoSearch = FALSE;
  2885. }
  2886. }
  2887. if (bDoSearch)
  2888. {
  2889. if (dwSearchForExtensions && dwSearchForExtensions != DONE_SUFFIXES)
  2890. {
  2891. wnsprintf(szT, ARRAYSIZE(szT), szSearchFormatStr, varURL.bstrVal);
  2892. if (!fAutoSearching)
  2893. {
  2894. _ValidateURL(szT, UQF_DEFAULT);
  2895. }
  2896. if (fAddMRU)
  2897. _UpdateMRU(pdoh, szT);
  2898. }
  2899. else if (VT_BSTR == varScanFailure.vt && NULL != varScanFailure.bstrVal)
  2900. {
  2901. StrCpyN(szT, varScanFailure.bstrVal, ARRAYSIZE(szT));
  2902. _ValidateURL(szT, UQF_DEFAULT);
  2903. _DontAddToMRU(pdoh);
  2904. }
  2905. else if (dwDo404Search)
  2906. {
  2907. // add the search prefix
  2908. StrCpyN(szT, TEXT("? "), ARRAYSIZE(szT));
  2909. StrCatBuff(szT, varURL.bstrVal, ARRAYSIZE(szT));
  2910. _DontAddToMRU(pdoh);
  2911. }
  2912. else
  2913. {
  2914. ASSERT(0);
  2915. }
  2916. if (dwSearchForExtensions && dwSearchForExtensions != DONE_SUFFIXES)
  2917. _SetSearchInfo(pdoh, ++dwSuffixIndex, FALSE, TRUE, FALSE);
  2918. else if (dwDo404Search)
  2919. _SetSearchInfo(pdoh, dwSuffixIndex, FALSE, FALSE, TRUE);
  2920. else
  2921. _SetSearchInfo(pdoh, 0, FALSE, FALSE, FALSE);
  2922. // If we're called from Trident (fFromTrident == TRUE), then we're going to call
  2923. // IHTMLPrivateWindow::SuperNavigate(). In that case, the call to _CancelPendingNavigation
  2924. // below needs to be synchronous. However, if we're going to call _DoAsyncNavigation,
  2925. // then the call to _CancelPendingNavigation needs to remain asynchronous.
  2926. //
  2927. if (!pdoh->_fCanceledByBrowser)
  2928. pdoh->_CancelPendingNavigation(FALSE, fFromTrident);
  2929. TraceMsg(TF_SHDNAVIGATE, "DOH::BSC::_HFNS() Doing search on %s", szT);
  2930. DWORD cchT = SIZECHARS(szT);
  2931. //
  2932. // if we can find a search context living in a host somewhere,
  2933. // then we need to pass that into ParseUrlFromOutsideSource
  2934. // because it'll use it to customize the behavior of
  2935. // the search hooks if a search ends up happening
  2936. //
  2937. ISearchContext * pSC = NULL;
  2938. pdoh->QueryService(SID_STopWindow, IID_ISearchContext, (void **)&pSC);
  2939. ParseURLFromOutsideSourceWithContextW(szT, szT, &cchT, NULL, pSC);
  2940. if (pSC != NULL)
  2941. {
  2942. pSC->Release();
  2943. }
  2944. if (fFromTrident)
  2945. {
  2946. BSTR bstrUrl = SysAllocString(szT);
  2947. IHTMLPrivateWindow * pPrivWindow = NULL;
  2948. ASSERT(pdoh->_fDocCanNavigate);
  2949. ASSERT(pdoh->_pHTMLWindow);
  2950. // The navigation state is already reset by cancelpending navigation
  2951. // causing either trident to cancel pending navigation or by OnStopBinding
  2952. /*
  2953. if (pdoh->_pwb)
  2954. pdoh->_pwb->SetNavigateState(BNS_NORMAL);
  2955. */
  2956. hres = pdoh->_pHTMLWindow->QueryInterface(IID_IHTMLPrivateWindow,
  2957. (void**)&pPrivWindow);
  2958. if (SUCCEEDED(hres))
  2959. {
  2960. hres = pPrivWindow->SuperNavigate(bstrUrl, NULL, NULL, NULL, NULL, NULL, 0);
  2961. pPrivWindow->Release();
  2962. }
  2963. SysFreeString(bstrUrl);
  2964. }
  2965. else
  2966. {
  2967. pdoh->_DoAsyncNavigation(szT);
  2968. }
  2969. pdoh->_fCanceledByBrowser = TRUE;
  2970. *pfShouldDisplayError = FALSE; // Don't display another dialog
  2971. hres = S_OK; // we did a navigate
  2972. }
  2973. VariantClear(&varScanFailure);
  2974. }
  2975. else if (bSentToEngine && !bSuppressUI)
  2976. {
  2977. *pfShouldDisplayError = FALSE;
  2978. _SetSearchInfo(pdoh, 0, FALSE, FALSE, FALSE);
  2979. IE_ErrorMsgBox(NULL, pdoh->_hwnd, hrDisplay, szError, szURL, IDS_CANTFINDSEARCH, MB_OK|MB_ICONSTOP);
  2980. hres = S_OK;
  2981. }
  2982. VariantClear(&varURL);
  2983. return hres;
  2984. } // _HandleFailedNavigationSearch()