dochostbsc.cpp
Upload User: xhy777
Upload Date: 2007-02-14
Package Size: 24088k
Code Size: 95k
Category:

Windows Kernel

Development Platform:

Visual C++

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