Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

9147 lines
283 KiB

  1. #include "priv.h"
  2. #include <mluisupp.h>
  3. // stuff that should be turned off while in here, but on when
  4. // it goes to commonsb or shbrows2.cpp
  5. #define IN_BASESB2
  6. #ifdef IN_BASESB2
  7. #define _fFullScreen FALSE
  8. #endif
  9. #include "sccls.h"
  10. #include <idhidden.h>
  11. #include "basesb.h"
  12. #include "iedde.h"
  13. #include "bindcb.h"
  14. #include "resource.h"
  15. #include "security.h"
  16. #include <urlmon.h>
  17. #include "favorite.h"
  18. #include "uemapp.h"
  19. #include <varutil.h>
  20. #include "interned.h" // IHTMLPrivateWindow
  21. #ifdef FEATURE_PICS
  22. #include <ratings.h>
  23. #include <ratingsp.h>
  24. #endif
  25. #include "msiehost.h"
  26. #include "dhuihand.h"
  27. #include "mypics.h"
  28. #include "airesize.h"
  29. #define DM_ACCELERATOR 0
  30. #define DM_WEBCHECKDRT 0
  31. #define DM_COCREATEHTML 0
  32. #define DM_CACHEOLESERVER 0
  33. #define DM_DOCCP 0
  34. #define DM_PICS 0
  35. #define DM_SSL 0
  36. #define DM_MISC DM_TRACE // misc/tmp
  37. // get at defs to run a privacy dialog box
  38. #include "privacyui.hpp"
  39. //
  40. // Remove this #include by defining _bbd._pauto as IWebBrowserApp, just like
  41. // Explorer.exe.
  42. //
  43. #include "hlframe.h"
  44. extern IUnknown* ClassHolder_Create(const CLSID* pclsid);
  45. extern HRESULT VariantClearLazy(VARIANTARG *pvarg);
  46. #define WMC_ASYNCOPERATION (WMC_RESERVED_FIRST + 0x0000)
  47. #define ISSPACE(ch) (((ch) == 32) || ((unsigned)((ch) - 9)) <= 13 - 9)
  48. #define IDT_STARTING_APP_TIMER 9001 // trying to pick a unique number... (THIS IS BOGUS! FIX THIS!)
  49. #define STARTING_APP_DURATION 2500
  50. UINT g_uMsgFileOpened = (UINT)-1; // Registered window message for file opens
  51. // _uActionQueued of WMC_ACYNCOPERATION specifies the operation.
  52. #define ASYNCOP_NIL 0
  53. #define ASYNCOP_GOTO 1
  54. #define ASYNCOP_ACTIVATEPENDING 2
  55. #define ASYNCOP_CANCELNAVIGATION 3
  56. void IEInitializeClassFactoryObject(IUnknown* punkAuto);
  57. BOOL ParseRefreshContent(LPWSTR pwzContent,
  58. UINT * puiDelay, LPWSTR pwzUrlBuf, UINT cchUrlBuf);
  59. #define VALIDATEPENDINGSTATE() ASSERT((_bbd._psvPending && _bbd._psfPending) || (!_bbd._psvPending && !_bbd._psfPending))
  60. #define DM_HTTPEQUIV TF_SHDNAVIGATE
  61. #define DM_NAV TF_SHDNAVIGATE
  62. #define DM_ZONE TF_SHDNAVIGATE
  63. #define DM_IEDDE DM_TRACE
  64. #define DM_CANCELMODE 0
  65. #define DM_UIWINDOW 0
  66. #define DM_ENABLEMODELESS TF_SHDNAVIGATE
  67. #define DM_EXPLORERMENU 0
  68. #define DM_BACKFORWARD 0
  69. #define DM_PROTOCOL 0
  70. #define DM_ITBAR 0
  71. #define DM_STARTUP 0
  72. #define DM_AUTOLIFE 0
  73. #define DM_PALETTE 0
  74. #define DM_PERSIST 0 // trace IPS::Load, ::Save, etc.
  75. #define DM_VIEWSTREAM DM_TRACE
  76. #define DM_FOCUS 0
  77. #define DM_FOCUS2 0 // like DM_FOCUS, but verbose
  78. // these two MUST be in order because we peek them together
  79. STDAPI SafeGetItemObject(IShellView *psv, UINT uItem, REFIID riid, void **ppv);
  80. extern HRESULT TargetQueryService(IUnknown *punk, REFIID riid, void **ppvObj);
  81. HRESULT CreateTravelLog(ITravelLog **pptl);
  82. HRESULT CreatePublicTravelLog(IBrowserService *pbs, ITravelLogEx *ptlx, ITravelLogStg **pptlstg);
  83. #ifdef MESSAGEFILTER
  84. /*
  85. * CMsgFilter - implementation of IMessageFilter
  86. *
  87. * Used to help distribute WM_TIMER messages during OLE operations when
  88. * we are busy. If we don't install the CoRegisterMessageFilter
  89. * then OLE can PeekMessage(PM_NOREMOVE) the timers such that they pile up
  90. * and fill the message queue.
  91. *
  92. */
  93. class CMsgFilter : public IMessageFilter {
  94. public:
  95. // *** IUnknown methods ***
  96. STDMETHODIMP QueryInterface(REFIID riid, void **ppvObj)
  97. {
  98. // This interface doesn't get QI'ed.
  99. ASSERT(FALSE);
  100. return E_NOINTERFACE;
  101. };
  102. STDMETHODIMP_(ULONG) AddRef(void) { return ++_cRef; };
  103. STDMETHODIMP_(ULONG) Release(void) { ASSERT(_cRef > 0);
  104. _cRef--;
  105. if (_cRef > 0)
  106. return _cRef;
  107. delete this;
  108. return 0;
  109. };
  110. // *** IMessageFilter specific methods ***
  111. STDMETHODIMP_(DWORD) HandleInComingCall(
  112. IN DWORD dwCallType,
  113. IN HTASK htaskCaller,
  114. IN DWORD dwTickCount,
  115. IN LPINTERFACEINFO lpInterfaceInfo)
  116. {
  117. if (_lpMFOld)
  118. return (_lpMFOld->HandleInComingCall(dwCallType, htaskCaller, dwTickCount, lpInterfaceInfo));
  119. else
  120. return SERVERCALL_ISHANDLED;
  121. };
  122. STDMETHODIMP_(DWORD) RetryRejectedCall(
  123. IN HTASK htaskCallee,
  124. IN DWORD dwTickCount,
  125. IN DWORD dwRejectType)
  126. {
  127. if (_lpMFOld)
  128. return (_lpMFOld->RetryRejectedCall(htaskCallee, dwTickCount, dwRejectType));
  129. else
  130. return 0xffffffff;
  131. };
  132. STDMETHODIMP_(DWORD) MessagePending(
  133. IN HTASK htaskCallee,
  134. IN DWORD dwTickCount,
  135. IN DWORD dwPendingType)
  136. {
  137. DWORD dw;
  138. MSG msg;
  139. // We can get released during the DispatchMessage call...
  140. // If it's our last release, we'll free ourselves and
  141. // fault when we dereference _lpMFOld... Make sure this
  142. // doesn't happen by increasing our refcount.
  143. //
  144. AddRef();
  145. while (PeekMessage(&msg, NULL, WM_TIMER, WM_TIMER, PM_REMOVE))
  146. {
  147. #ifndef DISPATCH_IETIMERS
  148. TCHAR szClassName[40];
  149. GetClassName(msg.hwnd, szClassName, ARRAYSIZE(szClassName));
  150. if (StrCmpI(szClassName, TEXT("Internet Explorer_Hidden")) != 0)
  151. {
  152. #endif
  153. DispatchMessage(&msg);
  154. #ifndef DISPATCH_IETIMERS
  155. }
  156. #endif
  157. }
  158. if (_lpMFOld)
  159. dw = (_lpMFOld->MessagePending(htaskCallee, dwTickCount, dwPendingType));
  160. else
  161. dw = PENDINGMSG_WAITDEFPROCESS;
  162. Release();
  163. return(dw);
  164. };
  165. CMsgFilter() : _cRef(1)
  166. {
  167. ASSERT(_lpMFOld == NULL);
  168. };
  169. BOOL Initialize()
  170. {
  171. return (CoRegisterMessageFilter((LPMESSAGEFILTER)this, &_lpMFOld) != S_FALSE);
  172. };
  173. void UnInitialize()
  174. {
  175. CoRegisterMessageFilter(_lpMFOld, NULL);
  176. // we shouldn't ever get called again, but after 30 minutes
  177. // of automation driving we once hit a function call above
  178. // and we dereferenced this old pointer and page faulted.
  179. ATOMICRELEASE(_lpMFOld);
  180. };
  181. protected:
  182. int _cRef;
  183. LPMESSAGEFILTER _lpMFOld;
  184. };
  185. #endif
  186. void IEHard_NavWarning(HWND hwnd, BOOL fIE);
  187. BOOL IEHard_ShowOnNavigateComplete(void);
  188. BOOL IEHard_HostedInIE(IUnknown* punk);
  189. //--------------------------------------------------------------------------
  190. // Detecting a memory leak
  191. //--------------------------------------------------------------------------
  192. HRESULT GetTopFrameOptions(IServiceProvider * psp, DWORD * pdwOptions)
  193. {
  194. IServiceProvider * pspTop;
  195. HRESULT hres = psp->QueryService(SID_STopLevelBrowser, IID_PPV_ARG(IServiceProvider, &pspTop));
  196. if (SUCCEEDED(hres))
  197. {
  198. ITargetFrame2 *ptgf;
  199. hres = pspTop->QueryService(SID_SContainerDispatch, IID_PPV_ARG(ITargetFrame2, &ptgf));
  200. if (SUCCEEDED(hres))
  201. {
  202. hres = ptgf->GetFrameOptions(pdwOptions);
  203. ptgf->Release();
  204. }
  205. pspTop->Release();
  206. }
  207. return hres;
  208. }
  209. void UpdateDesktopComponentName(LPCWSTR lpcwszURL, LPCWSTR lpcwszName)
  210. {
  211. IActiveDesktop * piad;
  212. if (SUCCEEDED(SHCoCreateInstance(NULL, &CLSID_ActiveDesktop, NULL, IID_PPV_ARG(IActiveDesktop, &piad))))
  213. {
  214. COMPONENT comp;
  215. comp.dwSize = SIZEOF(comp);
  216. if (SUCCEEDED(piad->GetDesktopItemBySource(lpcwszURL, &comp, 0)) && !comp.wszFriendlyName[0])
  217. {
  218. StrCpyNW(comp.wszFriendlyName, lpcwszName, ARRAYSIZE(comp.wszFriendlyName));
  219. piad->ModifyDesktopItem(&comp, COMP_ELEM_FRIENDLYNAME);
  220. piad->ApplyChanges(AD_APPLY_SAVE);
  221. }
  222. piad->Release();
  223. }
  224. }
  225. HRESULT CBaseBrowser2::_Initialize(HWND hwnd, IUnknown* pauto)
  226. {
  227. if (pauto)
  228. {
  229. pauto->AddRef();
  230. }
  231. else
  232. {
  233. CIEFrameAuto_CreateInstance(NULL, &pauto);
  234. }
  235. // Grab _pauto interfaces we use throughout this code.
  236. //
  237. if (pauto)
  238. {
  239. pauto->QueryInterface(IID_PPV_ARG(IWebBrowser2, &_bbd._pautoWB2));
  240. ASSERT(_bbd._pautoWB2);
  241. pauto->QueryInterface(IID_PPV_ARG(IExpDispSupport, &_bbd._pautoEDS));
  242. ASSERT(_bbd._pautoEDS);
  243. pauto->QueryInterface(IID_PPV_ARG(IShellService, &_bbd._pautoSS));
  244. ASSERT(_bbd._pautoSS);
  245. pauto->QueryInterface(IID_PPV_ARG(ITargetFrame2, &_ptfrm));
  246. ASSERT(_ptfrm);
  247. pauto->QueryInterface(IID_PPV_ARG(IHlinkFrame, &_bbd._phlf));
  248. ASSERT(_bbd._phlf);
  249. IHTMLWindow2 *pWindow;
  250. if( SUCCEEDED(GetWindowFromUnknown( pauto, &pWindow )) )
  251. {
  252. pWindow->QueryInterface(IID_PPV_ARG(IShellHTMLWindowSupport, &_phtmlWS));
  253. pWindow->Release( );
  254. }
  255. ASSERT( _phtmlWS );
  256. _pauto = pauto;
  257. }
  258. // _psbOuter?
  259. if (NULL == _bbd._phlf)
  260. {
  261. Release();
  262. return E_FAIL;
  263. }
  264. else
  265. {
  266. _SetWindow(hwnd);
  267. return S_OK;
  268. }
  269. }
  270. HRESULT CBaseBrowser2::InitializeTransitionSite()
  271. {
  272. return S_OK;
  273. }
  274. HRESULT CBaseBrowser2_CreateInstance(IUnknown* pUnkOuter, IUnknown** ppunk, LPCOBJECTINFO poi)
  275. {
  276. CBaseBrowser2 *pbb = new CBaseBrowser2(pUnkOuter);
  277. if (pbb)
  278. {
  279. *ppunk = pbb->_GetInner();
  280. return S_OK;
  281. }
  282. *ppunk = NULL;
  283. return E_OUTOFMEMORY;
  284. }
  285. CBaseBrowser2::CBaseBrowser2(IUnknown* punkAgg) :
  286. CAggregatedUnknown(punkAgg),
  287. _bptBrowser(BPT_DeferPaletteSupport)
  288. {
  289. TraceMsg(TF_SHDLIFE, "ctor CBaseBrowser2 %x", this);
  290. _bbd._uActivateState = SVUIA_ACTIVATE_FOCUS;
  291. _InitComCtl32();
  292. ASSERT(S_FALSE == _DisableModeless());
  293. ASSERT(_cp == CP_ACP);
  294. ASSERT(!_fNoTopLevelBrowser);
  295. ASSERT(!_dwDocFlags);
  296. _QueryOuterInterface(IID_PPV_ARG(IBrowserService2, &_pbsOuter));
  297. _QueryOuterInterface(IID_PPV_ARG(IBrowserService3, &_pbsOuter3));
  298. _QueryOuterInterface(IID_PPV_ARG(IShellBrowser, &_psbOuter));
  299. _QueryOuterInterface(IID_PPV_ARG(IServiceProvider, &_pspOuter));
  300. // The following are intercepted by CCommonBrowser, but we don't call 'em
  301. //_QueryOuterInterface(IID_PPV_ARG(IOleCommandTarget, &_pctOuter));
  302. //_QueryOuterInterface(IID_PPV_ARG(IInputObjectSite, &_piosOuter));
  303. _dwStartingAppTick = 0;
  304. }
  305. CBaseBrowser2::~CBaseBrowser2()
  306. {
  307. TraceMsg(TF_SHDLIFE, "dtor CBaseBrowser2 %x", this);
  308. // Are we releasing these too early (i.e. does anything in the
  309. // rest of this func rely on having the 'vtables' still be valid?)
  310. RELEASEOUTERINTERFACE(_pbsOuter);
  311. RELEASEOUTERINTERFACE(_pbsOuter3);
  312. RELEASEOUTERINTERFACE(_psbOuter);
  313. RELEASEOUTERINTERFACE(_pspOuter);
  314. // The following are intercepted by CCommonBrowser, but we don't call 'em
  315. //RELEASEOUTERINTERFACE(_pctOuter);
  316. //RELEASEOUTERINTERFACE(_piosOuter);
  317. ASSERT(_hdpaDLM == NULL); // subclass must free it.
  318. // finish tracking here
  319. if (_ptracking)
  320. {
  321. delete _ptracking;
  322. _ptracking = NULL;
  323. }
  324. //
  325. // Notes: Unlike IE3.0, we release CIEFrameAuto pointers here.
  326. //
  327. ATOMICRELEASE(_bbd._pautoWB2);
  328. ATOMICRELEASE(_bbd._pautoEDS);
  329. ATOMICRELEASE(_bbd._pautoSS);
  330. ATOMICRELEASE(_phtmlWS);
  331. ATOMICRELEASE(_bbd._phlf);
  332. ATOMICRELEASE(_ptfrm);
  333. ATOMICRELEASE(_pauto);
  334. ATOMICRELEASE(_punkSFHistory);
  335. // clean up our palette by simulating a switch out of palettized mode
  336. _bptBrowser = BPT_NotPalettized;
  337. _QueryNewPalette();
  338. ASSERT(!_bbd._phlf);
  339. ASSERT(!_ptfrm);
  340. ASSERT(S_FALSE == _DisableModeless());
  341. ASSERT(_bbd._hwnd==NULL);
  342. ATOMICRELEASE(_pact);
  343. ATOMICRELEASE(_pIUrlHistoryStg);
  344. ATOMICRELEASE(_pITravelLogStg);
  345. ATOMICRELEASE(_poleHistory);
  346. ATOMICRELEASE(_pstmHistory);
  347. ATOMICRELEASE(_bbd._ptl);
  348. ATOMICRELEASE(_pHTMLDocument);
  349. ATOMICRELEASE(_pphHistory);
  350. ATOMICRELEASE(_pDispViewLinkedWebOCFrame);
  351. #ifdef MESSAGEFILTER
  352. if (_lpMF)
  353. {
  354. IMessageFilter* lpMF = _lpMF;
  355. _lpMF = NULL;
  356. ((CMsgFilter *)lpMF)->UnInitialize();
  357. EVAL(lpMF->Release() == 0);
  358. }
  359. #endif
  360. // This is created during FileCabinet_CreateViewWindow2
  361. CShellViews_Delete(&_fldBase._cViews);
  362. // If the class factory object has been cached, unlock it and release.
  363. if (_pcfHTML)
  364. {
  365. _pcfHTML->LockServer(FALSE);
  366. _pcfHTML->Release();
  367. }
  368. ATOMICRELEASE(_pToolbarExt);
  369. }
  370. HRESULT CBaseBrowser2::v_InternalQueryInterface(REFIID riid, void **ppvObj)
  371. {
  372. static const QITAB qit[] = {
  373. QITABENT(CBaseBrowser2, IShellBrowser), // IID_IShellBrowser
  374. QITABENTMULTI(CBaseBrowser2, IOleWindow, IShellBrowser), // IID_IOleWindow
  375. QITABENT(CBaseBrowser2, IOleInPlaceUIWindow), // IID_IOleInPlaceUIWindow
  376. QITABENT(CBaseBrowser2, IOleCommandTarget), // IID_IOleCommandTarget
  377. QITABENT(CBaseBrowser2, IDropTarget), // IID_IDropTarget
  378. QITABENTMULTI(CBaseBrowser2, IBrowserService, IBrowserService3), // IID_IBrowserService
  379. QITABENTMULTI(CBaseBrowser2, IBrowserService2, IBrowserService3), // IID_IBrowserService2
  380. QITABENT(CBaseBrowser2, IBrowserService3), // IID_IBrowserService3
  381. QITABENT(CBaseBrowser2, IServiceProvider), // IID_IServiceProvider
  382. QITABENT(CBaseBrowser2, IOleContainer), // IID_IOleContainer
  383. QITABENT(CBaseBrowser2, IAdviseSink), // IID_IAdviseSink
  384. QITABENT(CBaseBrowser2, IInputObjectSite), // IID_IInputObjectSite
  385. QITABENT(CBaseBrowser2, IDocNavigate), // IID_IDocNavigate
  386. QITABENT(CBaseBrowser2, IPersistHistory), // IID_IPersistHistory
  387. QITABENT(CBaseBrowser2, IInternetSecurityMgrSite), // IID_IInternetSecurityMgrSite
  388. QITABENT(CBaseBrowser2, IVersionHost), // IID_IVersionHost
  389. QITABENT(CBaseBrowser2, IProfferService), // IID_IProfferService
  390. QITABENT(CBaseBrowser2, ITravelLogClient), // IID_ITravelLogClient
  391. QITABENT(CBaseBrowser2, ITravelLogClient2), // IID_ITravelLogClient2
  392. QITABENTMULTI(CBaseBrowser2, ITridentService, ITridentService2), // IID_ITridentService
  393. QITABENT(CBaseBrowser2, ITridentService2), // IID_ITridentService2
  394. QITABENT(CBaseBrowser2, IInitViewLinkedWebOC), // IID_IInitViewLinkedWebOC
  395. QITABENT(CBaseBrowser2, INotifyAppStart), // IID_INotifyAppStart
  396. { 0 },
  397. };
  398. return QISearch(this, qit, riid, ppvObj);
  399. }
  400. BOOL CBaseBrowser2::_IsViewMSHTML(IShellView * psv)
  401. {
  402. BOOL fIsMSHTML = FALSE;
  403. if (psv)
  404. {
  405. IPersist *pPersist = NULL;
  406. HRESULT hres = SafeGetItemObject(psv, SVGIO_BACKGROUND, IID_PPV_ARG(IPersist, &pPersist));
  407. if (SUCCEEDED(hres) && (pPersist != NULL))
  408. {
  409. CLSID clsid;
  410. hres = pPersist->GetClassID(&clsid);
  411. if (SUCCEEDED(hres) && IsEqualGUID(clsid, CLSID_HTMLDocument))
  412. fIsMSHTML = TRUE;
  413. pPersist->Release();
  414. }
  415. }
  416. return fIsMSHTML;
  417. }
  418. HRESULT CBaseBrowser2::ReleaseShellView()
  419. {
  420. // We're seeing some reentrancy here. If _cRefUIActivateSV is non-zero, it means we're
  421. // in the middle of UIActivating the shell view.
  422. //
  423. if (_cRefUIActivateSV)
  424. {
  425. TraceMsg(TF_WARNING,
  426. "CBB(%x)::ReleaseShellView _cRefUIActivateSV(%d)!=0 _bbd._psv=%x ABORTING",
  427. this, _cRefUIActivateSV, _bbd._psv);
  428. return S_OK;
  429. }
  430. BOOL fViewObjectChanged = FALSE;
  431. VALIDATEPENDINGSTATE();
  432. TraceMsg(DM_NAV, "CBaseBrowser2(%x)::ReleaseShellView(%x)", this, _bbd._psv);
  433. ATOMICRELEASE(_pdtView);
  434. if (_bbd._psv)
  435. {
  436. // Disable navigation while we are UIDeactivating/DestroyWindowing
  437. // the IShellView. Some OC/DocObject in it (such as ActiveMovie)
  438. // might have a message loop long enough to cause some reentrancy.
  439. _psbOuter->EnableModelessSB(FALSE);
  440. // Tell the shell's HTML window we are releasing the document.
  441. if (_phtmlWS)
  442. {
  443. _phtmlWS->ViewReleased();
  444. }
  445. //
  446. // We need to cancel the menu mode so that unmerging menu won't
  447. // destroy the menu we are dealing with (which caused GPF in USER).
  448. // DocObject needs to do appropriate thing for context menus.
  449. // (02-03-96 SatoNa)
  450. //
  451. HWND hwndCapture = GetCapture();
  452. TraceMsg(DM_CANCELMODE, "ReleaseShellView hwndCapture=%x _bbd._hwnd=%x", hwndCapture, _bbd._hwnd);
  453. if (hwndCapture && hwndCapture==_bbd._hwnd)
  454. {
  455. TraceMsg(DM_CANCELMODE, "ReleaseShellView Sending WM_CANCELMODE");
  456. SendMessage(_bbd._hwnd, WM_CANCELMODE, 0, 0);
  457. }
  458. //
  459. // We don't want to resize the previous view window while we are
  460. // navigating away from it.
  461. //
  462. TraceMsg(TF_SHDUIACTIVATE, "CSB::ReleaseShellView setting _fDontResizeView");
  463. _fDontResizeView = TRUE;
  464. // If the current view is still waiting for ReadyStateComplete,
  465. // and the view we're swapping in here does not support this property,
  466. // then we'll never go to ReadyStateComplete! Simulate it here:
  467. //
  468. // NOTE: ZekeL put this in _CancelNavigation which happened way too often.
  469. // I think this is the case he was trying to fix, but I don't remember
  470. // the bug number so I don't have a specific repro...
  471. //
  472. if (!_bbd._fIsViewMSHTML)
  473. {
  474. _fReleasingShellView = TRUE;
  475. OnReadyStateChange(_bbd._psv, READYSTATE_COMPLETE);
  476. _fReleasingShellView = FALSE;
  477. }
  478. // At one point during a LOR stress test, we got re-entered during
  479. // this UIActivate call (some rogue 3rd-party IShellView perhaps?)
  480. // which caused _psv to get freed, and we faulted during the unwind.
  481. // Gaurd against this by swapping the _psv out early.
  482. //
  483. IShellView* psv = _bbd._psv;
  484. _bbd._psv = NULL;
  485. if (psv)
  486. {
  487. psv->UIActivate(SVUIA_DEACTIVATE);
  488. if (_cRefUIActivateSV)
  489. {
  490. TraceMsg(TF_WARNING, "CBB(%x)::ReleaseShellView setting _bbd._psv = NULL (was %x) while _cRefUIActivateSV=%d",
  491. this, psv, _cRefUIActivateSV);
  492. }
  493. ATOMICRELEASE(_bbd._pctView);
  494. if (_pvo)
  495. {
  496. IAdviseSink *pSink;
  497. // paranoia: only blow away the advise sink if it is still us
  498. if (SUCCEEDED(_pvo->GetAdvise(NULL, NULL, &pSink)) && pSink)
  499. {
  500. if (pSink == SAFECAST(this, IAdviseSink *))
  501. _pvo->SetAdvise(0, 0, NULL);
  502. pSink->Release();
  503. }
  504. fViewObjectChanged = TRUE;
  505. ATOMICRELEASE(_pvo);
  506. }
  507. psv->SaveViewState();
  508. TraceMsg(DM_NAV, "ief NAV::%s %x",TEXT("ReleaseShellView Calling DestroyViewWindow"), psv);
  509. psv->DestroyViewWindow();
  510. UINT cRef = psv->Release();
  511. TraceMsg(DM_NAV, "ief NAV::%s %x %x",TEXT("ReleaseShellView called psv->Release"), psv, cRef);
  512. _bbd._hwndView = NULL;
  513. TraceMsg(TF_SHDUIACTIVATE, "CSB::ReleaseShellView resetting _fDontResizeView");
  514. _fDontResizeView = FALSE;
  515. if (_bbd._pidlCur)
  516. {
  517. ILFree(_bbd._pidlCur);
  518. _bbd._pidlCur = NULL;
  519. }
  520. }
  521. _psbOuter->EnableModelessSB(TRUE);
  522. //
  523. // If there is any blocked async operation AND we can navigate now,
  524. // unblock it now.
  525. //
  526. _MayUnblockAsyncOperation();
  527. }
  528. ATOMICRELEASE(_bbd._psf);
  529. if (fViewObjectChanged)
  530. _ViewChange(DVASPECT_CONTENT, -1);
  531. if (_bbd._pszTitleCur)
  532. {
  533. LocalFree(_bbd._pszTitleCur);
  534. _bbd._pszTitleCur = NULL;
  535. }
  536. // NOTES: (SatoNa)
  537. //
  538. // This is the best time to clean up the left-over from UI-negotiation
  539. // from the previous DocObject. Excel 97, for some reason, takes 16
  540. // pixels from the top (for the formula bar) when we UI-deactivate it
  541. // by callin gIOleDocumentView::UIActivate(FALSE), which we call above.
  542. //
  543. SetRect(&_rcBorderDoc, 0, 0, 0, 0);
  544. return S_OK;
  545. }
  546. void CBaseBrowser2::_StopCurrentView()
  547. {
  548. // send OLECMDID_STOP
  549. if (_bbd._pctView) // we must check!
  550. {
  551. _bbd._pctView->Exec(NULL, OLECMDID_STOP, OLECMDEXECOPT_DONTPROMPTUSER, NULL, NULL);
  552. }
  553. }
  554. //
  555. // This function synchronously cancels the pending navigation if any.
  556. //
  557. HRESULT CBaseBrowser2::_CancelPendingNavigation(BOOL fDontReleaseState)
  558. {
  559. TraceMsg(TF_SHDNAVIGATE, "CBB::_CancelPendingNavigation called");
  560. _StopAsyncOperation();
  561. HRESULT hres = S_FALSE;
  562. #ifndef NON_NATIVE_FRAMES
  563. if (_bbd._psvPending)
  564. {
  565. if (_IsViewMSHTML(_bbd._psvPending))
  566. {
  567. VARIANT varStop;
  568. V_VT(&varStop) = VT_BOOL;
  569. V_BOOL(&varStop) = VARIANT_TRUE;
  570. IUnknown_Exec(_bbd._psvPending, NULL, OLECMDID_STOP, 0, &varStop, NULL);
  571. }
  572. else
  573. {
  574. if (_bbd._phlf && !fDontReleaseState)
  575. {
  576. // release our state
  577. _bbd._phlf->Navigate(0, NULL, NULL, NULL);
  578. }
  579. _CancelPendingView();
  580. }
  581. hres = S_OK;
  582. }
  583. #else
  584. if (_bbd._psvPending)
  585. {
  586. if (_bbd._phlf && !fDontReleaseState)
  587. {
  588. // release our state
  589. _bbd._phlf->Navigate(0, NULL, NULL, NULL);
  590. }
  591. _CancelPendingView();
  592. hres = S_OK;
  593. }
  594. #endif
  595. return hres;
  596. }
  597. void CBaseBrowser2::_SendAsyncNavigationMsg(VARIANTARG *pvarargIn)
  598. {
  599. LPCWSTR psz = VariantToStrCast(pvarargIn);
  600. if (psz)
  601. {
  602. LPITEMIDLIST pidl;
  603. if (EVAL(SUCCEEDED(IECreateFromPathW(psz, &pidl))))
  604. {
  605. _NavigateToPidlAsync(pidl, 0); // takes ownership of pidl
  606. }
  607. }
  608. }
  609. //
  610. // NOTES: It does not cancel the pending view.
  611. //
  612. void CBaseBrowser2::_StopAsyncOperation(void)
  613. {
  614. // Don't remove posted WMC_ASYNCOPERATION message. PeekMesssage removes
  615. // messages for children! (SatoNa)
  616. _uActionQueued = ASYNCOP_NIL;
  617. // Remove the pidl in the queue (single depth)
  618. _FreeQueuedPidl(&_pidlQueued);
  619. }
  620. //
  621. // This function checks if we have any asynchronous operation AND
  622. // we no longer need to postpone. In that case, we unblock it by
  623. // posting a WMC_ASYNCOPERATION.
  624. //
  625. void CBaseBrowser2::_MayUnblockAsyncOperation(void)
  626. {
  627. if (_uActionQueued!=ASYNCOP_NIL && _CanNavigate())
  628. {
  629. TraceMsg(TF_SHDNAVIGATE, "CBB::_MayUnblockAsyncOp posting WMC_ASYNCOPERATION");
  630. PostMessage(_bbd._hwnd, WMC_ASYNCOPERATION, 0, 0);
  631. }
  632. }
  633. BOOL CBaseBrowser2::_PostAsyncOperation(UINT uAction)
  634. {
  635. _uActionQueued = uAction;
  636. return PostMessage(_bbd._hwnd, WMC_ASYNCOPERATION, 0, 0);
  637. }
  638. LRESULT CBaseBrowser2::_SendAsyncOperation(UINT uAction)
  639. {
  640. _uActionQueued = uAction;
  641. return SendMessage(_bbd._hwnd, WMC_ASYNCOPERATION, 0, 0);
  642. }
  643. HRESULT CBaseBrowser2::_CancelPendingNavigationAsync(void)
  644. {
  645. TraceMsg(TF_SHDNAVIGATE, "CBB::_CancelPendingNavigationAsync called");
  646. _StopAsyncOperation();
  647. _PostAsyncOperation(ASYNCOP_CANCELNAVIGATION);
  648. return S_OK;
  649. }
  650. HRESULT CBaseBrowser2::_CancelPendingView(void)
  651. {
  652. if (_bbd._psvPending)
  653. {
  654. TraceMsg(DM_NAV, "ief NAV::%s %x",TEXT("_CancelPendingView Calling DestroyViewWindow"), _bbd._psvPending);
  655. _bbd._psvPending->DestroyViewWindow();
  656. ASSERT(_bbd._psfPending);
  657. // When cancelling a pending navigation, make sure we
  658. // think the pending operation is _COMPLETE otherwise
  659. // we may get stuck in a _LOADING state...
  660. //
  661. TraceMsg(TF_SHDNAVIGATE, "basesb(%x) Fake pending ReadyState_Complete", this);
  662. OnReadyStateChange(_bbd._psvPending, READYSTATE_COMPLETE);
  663. ATOMICRELEASE(_bbd._psvPending);
  664. // Paranoia
  665. ATOMICRELEASE(_bbd._psfPending);
  666. _bbd._hwndViewPending = NULL;
  667. _setDescendentNavigate(NULL);
  668. SetNavigateState(BNS_NORMAL);
  669. if (_bbd._pidlPending)
  670. {
  671. ILFree(_bbd._pidlPending);
  672. _bbd._pidlPending = NULL;
  673. }
  674. if (_bbd._pszTitlePending)
  675. {
  676. LocalFree(_bbd._pszTitlePending);
  677. _bbd._pszTitlePending = NULL;
  678. }
  679. // Pending navigation is canceled.
  680. // since the back button works as a stop on pending navigations, we
  681. // should check that here as well.
  682. _pbsOuter->UpdateBackForwardState();
  683. _NotifyCommandStateChange();
  684. _PauseOrResumeView(_fPausedByParent);
  685. }
  686. return S_OK;
  687. }
  688. void CBaseBrowser2::_UpdateTravelLog(BOOL fForceUpdate /* = FALSE */)
  689. {
  690. //
  691. // we update the travellog in two parts. first we update
  692. // the current entry with the current state info,
  693. // then we create a new empty entry. UpdateEntry()
  694. // and AddEntry() need to always be in pairs, with
  695. // identical parameters.
  696. //
  697. // if this navigation came from a LoadHistory, the
  698. // _fDontAddTravelEntry will be set, and the update and
  699. // cursor movement will have been adjusted already.
  700. // we also want to prevent new frames from updating
  701. // and adding stuff, so unless this is the top we
  702. // wont add to the travellog if this is a new frame.
  703. //
  704. ASSERT(!(_grfHLNFPending & HLNF_CREATENOHISTORY));
  705. ITravelLog *ptl;
  706. GetTravelLog(&ptl);
  707. BOOL fTopFrameBrowser = IsTopFrameBrowser(SAFECAST(this, IServiceProvider *), SAFECAST(this, IShellBrowser *));
  708. if (ptl)
  709. {
  710. //
  711. // some times we are started by another app (MSWORD usually) that has HLink
  712. // capability. we detect this by noting that we are a new browser with an empty
  713. // TravelLog, and then see if we can get a IHlinkBrowseContext. if this is successful,
  714. // we should add an entry and update it immediately with the external info.
  715. //
  716. IHlinkBrowseContext *phlbc = NULL; // init to suppress bogus C4701 warning
  717. BOOL fExternalNavigate = (FAILED(ptl->GetTravelEntry(SAFECAST(this, IBrowserService *), 0, NULL)) &&
  718. fTopFrameBrowser && _bbd._phlf && SUCCEEDED(_bbd._phlf->GetBrowseContext(&phlbc)));
  719. if (fExternalNavigate)
  720. {
  721. ptl->AddEntry(SAFECAST(this, IBrowserService *), FALSE);
  722. ptl->UpdateExternal(SAFECAST(this, IBrowserService *), phlbc);
  723. phlbc->Release();
  724. }
  725. else if (_bbd._psv && (fForceUpdate || !_fIsLocalAnchor || (_dwDocFlags & DOCFLAG_DOCCANNAVIGATE)))
  726. {
  727. ptl->UpdateEntry(SAFECAST(this, IBrowserService *), _fIsLocalAnchor); // CAST for IUnknown
  728. }
  729. if (!_fDontAddTravelEntry && (_bbd._psv || fTopFrameBrowser))
  730. {
  731. ptl->AddEntry(SAFECAST(this, IBrowserService *), _fIsLocalAnchor); // CAST for IUnknown
  732. }
  733. ptl->Release();
  734. }
  735. _fDontAddTravelEntry = FALSE;
  736. _fIsLocalAnchor = FALSE;
  737. }
  738. void CBaseBrowser2::_OnNavigateComplete(LPCITEMIDLIST pidl, DWORD grfHLNF)
  739. {
  740. _pbsOuter->UpdateBackForwardState();
  741. }
  742. //// Does only the top shbrowse need this? or the top oc frame too?
  743. HRESULT CBaseBrowser2::UpdateSecureLockIcon(int eSecureLock)
  744. {
  745. // only the top boy should get to set his stuff
  746. if (!IsTopFrameBrowser(SAFECAST(this, IServiceProvider *), SAFECAST(this, IShellBrowser *)))
  747. return S_OK;
  748. if (eSecureLock != SECURELOCK_NOCHANGE)
  749. _bbd._eSecureLockIcon = eSecureLock;
  750. //
  751. // There is no mixed Security Icon - zekel 6-AUG-97
  752. // right now we have no icon or TT for SECURELOCK_SET_MIXED, which
  753. // is set when the root page is secure but some of the other content
  754. // or frames are not. some PM needs to implement, probably
  755. // with consultation from TonyCi and DBau. by default we currently
  756. // only show for pages that are completely secure.
  757. //
  758. TraceMsg(DM_SSL, "CBB:UpdateSecureLockIcon() _bbd._eSecureLockIcon = %d", _bbd._eSecureLockIcon);
  759. //
  760. // It looks like it doesnt matter what icon we select here,
  761. // the status bar always shows some lock icon that was cached there earlier
  762. // and it treats this HICON as a bool to indicat on or off - zekel - 5-DEC-97
  763. //
  764. HICON hicon = NULL;
  765. TCHAR szText[MAX_TOOLTIP_STRING];
  766. szText[0] = 0;
  767. switch (_bbd._eSecureLockIcon)
  768. {
  769. case SECURELOCK_SET_UNSECURE:
  770. case SECURELOCK_SET_MIXED:
  771. hicon = NULL;
  772. break;
  773. case SECURELOCK_SET_SECUREUNKNOWNBIT:
  774. hicon = g_hiconSSL;
  775. break;
  776. case SECURELOCK_SET_SECURE40BIT:
  777. hicon = g_hiconSSL;
  778. MLLoadString(IDS_SSL40, szText, ARRAYSIZE(szText));
  779. break;
  780. case SECURELOCK_SET_SECURE56BIT:
  781. hicon = g_hiconSSL;
  782. MLLoadString(IDS_SSL56, szText, ARRAYSIZE(szText));
  783. break;
  784. case SECURELOCK_SET_SECURE128BIT:
  785. hicon = g_hiconSSL;
  786. MLLoadString(IDS_SSL128, szText, ARRAYSIZE(szText));
  787. break;
  788. case SECURELOCK_SET_FORTEZZA:
  789. hicon = g_hiconFortezza;
  790. MLLoadString(IDS_SSL_FORTEZZA, szText, ARRAYSIZE(szText));
  791. break;
  792. default:
  793. ASSERT(0);
  794. return E_FAIL;
  795. }
  796. VARIANTARG var = {0};
  797. if (_bbd._pctView && SUCCEEDED(_bbd._pctView->Exec(&CGID_Explorer, SBCMDID_GETPANE, PANE_SSL, NULL, &var))
  798. && V_UI4(&var) != PANE_NONE)
  799. {
  800. _psbOuter->SendControlMsg(FCW_STATUS, SB_SETICON, V_UI4(&var), (LPARAM)(hicon), NULL);
  801. _psbOuter->SendControlMsg(FCW_STATUS, SB_SETTIPTEXT, V_UI4(&var), (LPARAM)(szText[0] ? szText : NULL), NULL);
  802. // Also add the tip text as the pane's normal text. Because of the pane's size it will be clipped,
  803. // but it will show up as a useful string in MSAA.
  804. _psbOuter->SendControlMsg(FCW_STATUS, SB_SETTEXTW, V_UI4(&var), (LPARAM)(szText[0] ? szText : NULL), NULL);
  805. }
  806. return S_OK;
  807. }
  808. //
  809. // Update Privacy Icon
  810. //
  811. HRESULT CBaseBrowser2::_UpdatePrivacyIcon(BOOL fSetState, BOOL fNewImpacted)
  812. {
  813. static BOOL fHelpShown = FALSE;
  814. //
  815. // only the top boy should get to set his stuff
  816. //
  817. if (!IsTopFrameBrowser(SAFECAST(this, IServiceProvider *), SAFECAST(this, IShellBrowser *)))
  818. return S_OK;
  819. //
  820. // save off the privacy state
  821. //
  822. if(fSetState)
  823. {
  824. _bbd._fPrivacyImpacted = fNewImpacted;
  825. }
  826. HICON hicon = NULL;
  827. TCHAR szText[MAX_TOOLTIP_STRING];
  828. szText[0] = 0;
  829. if(_bbd._fPrivacyImpacted)
  830. {
  831. hicon = g_hiconPrivacyImpact;
  832. MLLoadString(IDS_PRIVACY_TOOLTIP, szText, ARRAYSIZE(szText));
  833. }
  834. if (_bbd._pctView)
  835. {
  836. _psbOuter->SendControlMsg(FCW_STATUS, SB_SETICON, STATUS_PANE_PRIVACY, (LPARAM)(hicon), NULL);
  837. _psbOuter->SendControlMsg(FCW_STATUS, SB_SETTIPTEXT, STATUS_PANE_PRIVACY, (LPARAM)(szText[0] ? szText : NULL), NULL);
  838. // Also add the tip text as the panes normal text. Because of the pane's size it will be clipped,
  839. // but it will show up as a useful string in MSAA.
  840. _psbOuter->SendControlMsg(FCW_STATUS, SB_SETTEXTW, STATUS_PANE_PRIVACY, (LPARAM)(szText[0] ? szText : NULL), NULL);
  841. }
  842. // if impacted and never shown before, show bubble toolhelp
  843. if(FALSE == fHelpShown && _bbd._fPrivacyImpacted)
  844. {
  845. DWORD dwValue, dwSize;
  846. // only do this work once
  847. fHelpShown = TRUE;
  848. // Check to see if we should show discovery UI
  849. dwSize = sizeof(DWORD);
  850. if(ERROR_SUCCESS != SHGetValueW(HKEY_CURRENT_USER,
  851. REGSTR_PATH_INTERNET_SETTINGS,
  852. REGSTR_VAL_PRIVDISCOVER,
  853. NULL, &dwValue, &dwSize)
  854. || 0 == dwValue)
  855. {
  856. BOOL bStatusBarVisible = FALSE;
  857. INT_PTR i = 1;
  858. HRESULT hr;
  859. // suppression setting not set, show ui if status bar is visible
  860. IBrowserService *pbs;
  861. hr = _pspOuter->QueryService(SID_STopFrameBrowser, IID_PPV_ARG(IBrowserService, &pbs));
  862. if(SUCCEEDED(hr))
  863. {
  864. hr = pbs->IsControlWindowShown(FCW_STATUS, &bStatusBarVisible);
  865. pbs->Release();
  866. }
  867. BOOL fDontShowPrivacyFirstTimeDialogAgain = FALSE;
  868. if(SUCCEEDED(hr) && bStatusBarVisible)
  869. {
  870. fDontShowPrivacyFirstTimeDialogAgain = DoPrivacyFirstTimeDialog( _bbd._hwnd);
  871. }
  872. if( fDontShowPrivacyFirstTimeDialogAgain == TRUE)
  873. {
  874. dwValue = 1;
  875. SHSetValue(HKEY_CURRENT_USER, REGSTR_PATH_INTERNET_SETTINGS, REGSTR_VAL_PRIVDISCOVER,
  876. REG_DWORD, &dwValue, sizeof(DWORD));
  877. }
  878. }
  879. }
  880. return S_OK;
  881. }
  882. //
  883. // This block of code simply prevents calling UIActivate of old
  884. // extensions with a new SVUIA_ value.
  885. //
  886. HRESULT CBaseBrowser2::_UIActivateView(UINT uState)
  887. {
  888. if (_bbd._psv)
  889. {
  890. BOOL fShellView2;
  891. IShellView2* psv2;
  892. if (SUCCEEDED(_bbd._psv->QueryInterface(IID_PPV_ARG(IShellView2, &psv2))))
  893. {
  894. fShellView2 = TRUE;
  895. psv2->Release();
  896. }
  897. else
  898. {
  899. fShellView2 = FALSE;
  900. }
  901. if (uState == SVUIA_INPLACEACTIVATE && !fShellView2)
  902. {
  903. uState = SVUIA_ACTIVATE_NOFOCUS; // map it to old one.
  904. }
  905. if (_cRefUIActivateSV)
  906. {
  907. TraceMsg(TF_WARNING, "CBB(%x)::_UIActivateView(%d) entered reentrantly!!!!!! _cRefUIActivate=%d",
  908. this, uState, _cRefUIActivateSV);
  909. if (uState == SVUIA_DEACTIVATE)
  910. {
  911. _fDeferredUIDeactivate = TRUE;
  912. return S_OK;
  913. }
  914. if (!_HeyMoe_IsWiseGuy())
  915. {
  916. if (_bbd._psv)
  917. _bbd._psv->UIActivate(SVUIA_INPLACEACTIVATE);
  918. return S_OK;
  919. }
  920. }
  921. _cRefUIActivateSV++;
  922. TraceMsg(TF_SHDUIACTIVATE, "CBaseBrowser2(%x)::_UIActivateView(%d) about to call _bbd._psv(%x)->UIActivate",
  923. this, uState, _bbd._psv);
  924. _bbd._psv->UIActivate(uState);
  925. if (uState == SVUIA_ACTIVATE_FOCUS && !fShellView2)
  926. {
  927. // win95 defview expects a SetFocus on activation (nt5 bug#172210)
  928. if (_bbd._hwndView)
  929. SetFocus(_bbd._hwndView);
  930. }
  931. TraceMsg(TF_SHDUIACTIVATE, "CBaseBrowser2(%x)::_UIActivateView(%d) back from _bbd._psv(%x)->UIActivate",
  932. this, uState, _bbd._psv);
  933. _cRefUIActivateSV--;
  934. _UpdatePrivacyIcon(FALSE, FALSE);
  935. UpdateSecureLockIcon(SECURELOCK_NOCHANGE);
  936. }
  937. _bbd._uActivateState = uState;
  938. // If this is a pending view, set the focus to its window even though it's hidden.
  939. // In ActivatePendingView(), we check if this window still has focus and, if it does,
  940. // we will ui-activate the view. Fix for IE5 bug #70632 -- MohanB
  941. if ( SVUIA_ACTIVATE_FOCUS == uState
  942. && !_bbd._psv
  943. && !_bbd._hwndView
  944. && _bbd._psvPending
  945. && _bbd._hwndViewPending
  946. )
  947. {
  948. ::SetFocus(_bbd._hwndViewPending);
  949. }
  950. if (_fDeferredUIDeactivate)
  951. {
  952. TraceMsg(TF_SHDUIACTIVATE, "CBaseBrowser2(%x)::_UIActivateView processing deferred UIDeactivate, _bbd._psv=%x",
  953. this, _bbd._psv);
  954. _fDeferredUIDeactivate = FALSE;
  955. if (_bbd._psv)
  956. _bbd._psv->UIActivate(SVUIA_DEACTIVATE);
  957. _UpdatePrivacyIcon(FALSE, FALSE);
  958. UpdateSecureLockIcon(SECURELOCK_NOCHANGE);
  959. _bbd._uActivateState = SVUIA_DEACTIVATE;
  960. }
  961. if (_fDeferredSelfDestruction)
  962. {
  963. TraceMsg(TF_SHDUIACTIVATE, "CBaseBrowser2(%x)::_UIActivateView processing deferred OnDestroy",
  964. this);
  965. _fDeferredSelfDestruction = FALSE;
  966. _pbsOuter->OnDestroy();
  967. }
  968. return S_OK;
  969. }
  970. //Called from CShellBrowser::OnCommand
  971. HRESULT CBaseBrowser2::Offline(int iCmd)
  972. {
  973. HRESULT hresIsOffline = IsGlobalOffline() ? S_OK : S_FALSE;
  974. switch(iCmd){
  975. case SBSC_TOGGLE:
  976. hresIsOffline = (hresIsOffline == S_OK) ? S_FALSE : S_OK; // Toggle Property
  977. // Tell wininet that the user wants to go offline
  978. SetGlobalOffline(hresIsOffline == S_OK);
  979. SendShellIEBroadcastMessage(WM_WININICHANGE,0,0, 1000); // Tell all browser windows to update their title
  980. break;
  981. case SBSC_QUERY:
  982. break;
  983. default: // Treat like a query
  984. break;
  985. }
  986. return hresIsOffline;
  987. }
  988. BOOL _TrackPidl(LPITEMIDLIST pidl, IUrlHistoryPriv *php, BOOL fIsOffline, LPTSTR pszUrl, DWORD cchUrl)
  989. {
  990. BOOL fRet = FALSE;
  991. // Should use IsBrowserFrameOptionsPidlSet(pidl, BFO_ENABLE_HYPERLINK_TRACKING)
  992. // instead of IsURLChild() because it doesn't work in Folder Shortcuts and doesn't
  993. // work in NSEs outside of the "IE" name space (like Web Folders).
  994. if (pidl && IsURLChild(pidl, FALSE))
  995. {
  996. if (SUCCEEDED(IEGetNameAndFlags(pidl, SHGDN_FORPARSING, pszUrl, cchUrl, NULL)))
  997. {
  998. PROPVARIANT vProp;
  999. if (SUCCEEDED(php->GetProperty(pszUrl, PID_INTSITE_TRACKING, &vProp)))
  1000. {
  1001. if (vProp.vt == VT_UI4)
  1002. {
  1003. if (fIsOffline)
  1004. fRet = (vProp.ulVal & TRACK_OFFLINE_CACHE_ENTRY) ? TRUE : FALSE;
  1005. else
  1006. fRet = (vProp.ulVal & TRACK_ONLINE_CACHE_ENTRY) ? TRUE : FALSE;
  1007. }
  1008. PropVariantClear(&vProp);
  1009. }
  1010. }
  1011. }
  1012. return fRet;
  1013. }
  1014. // End tracking of previous page
  1015. // May start tracking of new page
  1016. // use SatoN's db to quick check tracking/tracking scope bits, so
  1017. // to eliminate call to CUrlTrackingStg::IsOnTracking
  1018. void CBaseBrowser2::_MayTrackClickStream(LPITEMIDLIST pidlNew)
  1019. {
  1020. BOOL fIsOffline = (Offline(SBSC_QUERY) != S_FALSE);
  1021. IUrlHistoryStg* phist;
  1022. IUrlHistoryPriv* phistp;
  1023. PROPVARIANT vProp = {0};
  1024. TCHAR szUrl[MAX_URL_STRING];
  1025. ASSERT(_bbd._pautoWB2);
  1026. HRESULT hr = _pspOuter->QueryService(SID_STopLevelBrowser, IID_PPV_ARG(IUrlHistoryStg, &phist));
  1027. if (SUCCEEDED(hr))
  1028. {
  1029. hr = phist->QueryInterface(IID_PPV_ARG(IUrlHistoryPriv, &phistp));
  1030. phist->Release();
  1031. }
  1032. if (SUCCEEDED(hr))
  1033. {
  1034. if (_TrackPidl(_bbd._pidlCur, phistp, fIsOffline, szUrl, SIZECHARS(szUrl)))
  1035. {
  1036. if (_ptracking)
  1037. _ptracking->OnUnload(szUrl);
  1038. else
  1039. hr = E_FAIL;
  1040. }
  1041. }
  1042. if (SUCCEEDED(hr))
  1043. {
  1044. if (_TrackPidl(pidlNew, phistp, fIsOffline, szUrl, SIZECHARS(szUrl)))
  1045. {
  1046. // instance of object already exists
  1047. BRMODE brMode = BM_NORMAL;
  1048. DWORD dwOptions;
  1049. if (!_ptracking)
  1050. {
  1051. _ptracking = new CUrlTrackingStg();
  1052. if (!_ptracking)
  1053. hr = E_OUTOFMEMORY;
  1054. }
  1055. if (SUCCEEDED(hr))
  1056. {
  1057. hr = GetTopFrameOptions(_pspOuter, &dwOptions);
  1058. if (SUCCEEDED(hr))
  1059. {
  1060. //Is this a desktop component?
  1061. if (dwOptions & FRAMEOPTIONS_DESKTOP)
  1062. brMode = BM_DESKTOP;
  1063. //Is it fullscreen?
  1064. else if (dwOptions & (FRAMEOPTIONS_SCROLL_AUTO | FRAMEOPTIONS_NO3DBORDER))
  1065. brMode = BM_THEATER;
  1066. }
  1067. _ptracking->OnLoad(szUrl, brMode, FALSE);
  1068. }
  1069. }
  1070. }
  1071. phistp->Release();
  1072. }
  1073. HRESULT CBaseBrowser2::_SwitchActivationNow()
  1074. {
  1075. ASSERT(_bbd._psvPending);
  1076. WORD wNavTypeFlags = 0; // init to suppress bogus C4701 warning
  1077. IShellView* psvNew = _bbd._psvPending;
  1078. IShellFolder* psfNew = _bbd._psfPending;
  1079. HWND hwndViewNew = _bbd._hwndViewPending;
  1080. LPITEMIDLIST pidlNew = _bbd._pidlPending;
  1081. _bbd._fIsViewMSHTML = _IsViewMSHTML(psvNew);
  1082. _bbd._psvPending = NULL;
  1083. _bbd._psfPending = NULL;
  1084. _bbd._hwndViewPending = NULL;
  1085. _bbd._pidlPending = NULL;
  1086. // Quickly check tracking prefix string on this page,
  1087. // if turned on, log enter/exit events
  1088. // Should use IsBrowserFrameOptionsSet(_bbd._psf, BFO_ENABLE_HYPERLINK_TRACKING)
  1089. // instead of IsURLChild() because it doesn't work in Folder Shortcuts and doesn't
  1090. // work in NSEs outside of the "IE" name space (like Web Folders).
  1091. if ((_bbd._pidlCur && IsURLChild(_bbd._pidlCur, FALSE)) ||
  1092. (pidlNew && IsURLChild(pidlNew, FALSE)))
  1093. _MayTrackClickStream(pidlNew);
  1094. // nuke the old stuff
  1095. _pbsOuter->ReleaseShellView();
  1096. ASSERT(!_bbd._psv && !_bbd._psf && !_bbd._hwndView);
  1097. // activate the new stuff
  1098. if (_grfHLNFPending != (DWORD)-1)
  1099. {
  1100. _OnNavigateComplete(pidlNew, _grfHLNFPending);
  1101. }
  1102. VALIDATEPENDINGSTATE();
  1103. // now do the actual switch
  1104. // no need to addref because we're keeping the pointer and just chaning
  1105. // it from the pending to the current member variables
  1106. _bbd._psf = psfNew;
  1107. _bbd._psv = psvNew;
  1108. ILFree(_bbd._pidlCur);
  1109. _bbd._pidlCur = pidlNew;
  1110. DEBUG_CODE(TCHAR szPath[INTERNET_MAX_URL_LENGTH + 1];)
  1111. DEBUG_CODE(IEGetDisplayName(_bbd._pidlCur, szPath, SHGDN_FORPARSING);)
  1112. DEBUG_CODE(TraceMsg(DM_TRACE, "CBB::ActivatePendingView (TRAVELLOG): _UpdateTravelLog called from shdocvw for %ws", szPath);)
  1113. _bbd._hwndView = hwndViewNew;
  1114. _dwReadyStateCur = _dwReadyStatePending;
  1115. if (_bbd._pszTitleCur)
  1116. LocalFree(_bbd._pszTitleCur);
  1117. _bbd._pszTitleCur = _bbd._pszTitlePending;
  1118. _bbd._pszTitlePending = NULL;
  1119. if (_eSecureLockIconPending != SECURELOCK_NOCHANGE)
  1120. {
  1121. _bbd._eSecureLockIcon = _eSecureLockIconPending;
  1122. _eSecureLockIconPending = SECURELOCK_NOCHANGE;
  1123. }
  1124. //
  1125. // This is the best time to resize the newone.
  1126. //
  1127. _pbsOuter->_UpdateViewRectSize();
  1128. SetWindowPos(_bbd._hwndView, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
  1129. // WARNING: Not all shellview supports IOleCommandTarget!!!
  1130. _fUsesPaletteCommands = FALSE;
  1131. if ( _bbd._psv )
  1132. {
  1133. _bbd._psv->QueryInterface(IID_PPV_ARG(IOleCommandTarget, &_bbd._pctView));
  1134. // PALETTE: Exec down to see if they support the colors changes Command so that we don't have to
  1135. // PALETTE: wire ourselves into the OnViewChange mechanism just to get palette changes...
  1136. if ( _bbd._pctView &&
  1137. SUCCEEDED(_bbd._pctView->Exec( &CGID_ShellDocView, SHDVID_CANDOCOLORSCHANGE, 0, NULL, NULL)))
  1138. {
  1139. _fUsesPaletteCommands = TRUE;
  1140. // force a colors dirty to make sure that we check for a new palette for each page...
  1141. _ColorsDirty( BPT_UnknownPalette );
  1142. }
  1143. }
  1144. // PALETTE: only register for the OnViewChange stuff if the above exec failed...
  1145. if (SUCCEEDED(_bbd._psv->QueryInterface(IID_PPV_ARG(IViewObject, &_pvo))) && !_fUsesPaletteCommands )
  1146. _pvo->SetAdvise(DVASPECT_CONTENT, ADVF_PRIMEFIRST, this);
  1147. _Exec_psbMixedZone();
  1148. if (_bbd._pctView != NULL)
  1149. {
  1150. _bbd._pctView->Exec(&CGID_ShellDocView, SHDVID_RESETSTATUSBAR, 0, NULL, NULL);
  1151. }
  1152. return S_OK;
  1153. }
  1154. // This member is called when we about to destroy the current shell view.
  1155. // Returning S_FALSE indicate that the user hit CANCEL when it is prompted
  1156. // to save the changes (if any).
  1157. HRESULT CBaseBrowser2::_MaySaveChanges(void)
  1158. {
  1159. HRESULT hres = S_OK;
  1160. if (_bbd._pctView) // we must check!
  1161. {
  1162. hres = _bbd._pctView->Exec(&CGID_Explorer, SBCMDID_MAYSAVECHANGES,
  1163. OLECMDEXECOPT_PROMPTUSER, NULL, NULL);
  1164. }
  1165. return hres;
  1166. }
  1167. HRESULT CBaseBrowser2::_DisableModeless(void)
  1168. {
  1169. if (_cRefCannotNavigate == 0)
  1170. {
  1171. OLECMD rgCmd;
  1172. BOOL fPendingInScript = FALSE;
  1173. // if pending shell view supports it, give it a chance to tell us it's not ready
  1174. // to deactivate [eg executing a script]. normally scripts should not be run
  1175. // before inplace activation, but TRIDENT sometimes has to do this when parsing.
  1176. //
  1177. rgCmd.cmdID = SHDVID_CANDEACTIVATENOW;
  1178. rgCmd.cmdf = 0;
  1179. if (SUCCEEDED(IUnknown_QueryStatus(_bbd._psvPending, &CGID_ShellDocView, 1, &rgCmd, NULL)) &&
  1180. (rgCmd.cmdf & MSOCMDF_SUPPORTED) &&
  1181. !(rgCmd.cmdf & MSOCMDF_ENABLED))
  1182. {
  1183. fPendingInScript = TRUE;
  1184. }
  1185. if (!fPendingInScript)
  1186. {
  1187. return S_FALSE;
  1188. }
  1189. }
  1190. return S_OK;
  1191. }
  1192. BOOL CBaseBrowser2::_CanNavigate(void)
  1193. {
  1194. return !((_DisableModeless() == S_OK) || (! IsWindowEnabled(_bbd._hwnd)));
  1195. }
  1196. HRESULT CBaseBrowser2::CanNavigateNow(void)
  1197. {
  1198. return _CanNavigate() ? S_OK : S_FALSE;
  1199. }
  1200. HRESULT CBaseBrowser2::_PauseOrResumeView(BOOL fPaused)
  1201. {
  1202. // If fPaused (it's minimized or the parent is minimized) or
  1203. // _bbd._psvPending is non-NULL, we need to pause.
  1204. if (_bbd._pctView)
  1205. {
  1206. VARIANT var = { 0 };
  1207. var.vt = VT_I4;
  1208. var.lVal = (_bbd._psvPending || fPaused) ? FALSE : TRUE;
  1209. _bbd._pctView->Exec(NULL, OLECMDID_ENABLE_INTERACTION, OLECMDEXECOPT_DONTPROMPTUSER, &var, NULL);
  1210. }
  1211. return S_OK;
  1212. }
  1213. HRESULT CBaseBrowser2::CreateViewWindow(IShellView* psvNew, IShellView* psvOld, LPRECT prcView, HWND* phwnd)
  1214. {
  1215. _fCreateViewWindowPending = TRUE;
  1216. _pbsOuter->GetFolderSetData(&(_fldBase._fld)); // it's okay to stomp on this every time
  1217. HRESULT hres = FileCabinet_CreateViewWindow2(_psbOuter, &_fldBase, psvNew, psvOld, prcView, phwnd);
  1218. _fCreateViewWindowPending = FALSE;
  1219. return hres;
  1220. }
  1221. //
  1222. // grfHLNF == (DWORD)-1 means don't touch the history at all.
  1223. //
  1224. // NOTE:
  1225. // if _fCreateViewWindowPending == TRUE, it means we came through here once
  1226. // already, but we are activating a synchronous view and the previous view would
  1227. // not deactivate immediately...
  1228. // It is used to delay calling IShellView::CreateViewWindow() for shell views until we know that
  1229. // we can substitute psvNew for _bbd._psv.
  1230. //
  1231. HRESULT CBaseBrowser2::_CreateNewShellView(IShellFolder* psf, LPCITEMIDLIST pidl, DWORD grfHLNF)
  1232. {
  1233. BOOL fActivatePendingView = FALSE;
  1234. IShellView *psvNew = NULL;
  1235. // Bail Out of Navigation if modal windows are up from our view
  1236. // Should we restart navigation on next EnableModeless(TRUE)?
  1237. if (!_CanNavigate())
  1238. {
  1239. TraceMsg(DM_ENABLEMODELESS, "CSB::_CreateNewShellView returning ERROR_BUSY");
  1240. return HRESULT_FROM_WIN32(ERROR_BUSY);
  1241. }
  1242. HRESULT hres = _MaySaveChanges();
  1243. if (hres == S_FALSE)
  1244. {
  1245. TraceMsg(DM_WARNING, "CBB::_CreateNewShellView _MaySaveChanges returned S_FALSE. Navigation canceled");
  1246. return HRESULT_FROM_WIN32(ERROR_CANCELLED);
  1247. }
  1248. TraceMsg(DM_WARNING, "CBB::_CNSV - Cur View MSHTML? %d Pending View MSHTML? %d",
  1249. _IsViewMSHTML(_bbd._psv), _IsViewMSHTML(_bbd._psvPending));
  1250. VALIDATEPENDINGSTATE();
  1251. #ifndef NON_NATIVE_FRAMES
  1252. // The navigation has been interrupted.
  1253. //
  1254. if ( _bbd._psv
  1255. && _bbd._psvPending
  1256. && _IsViewMSHTML(_bbd._psvPending))
  1257. {
  1258. _fHtmlNavCanceled = TRUE;
  1259. }
  1260. #endif
  1261. _CancelPendingView();
  1262. ASSERT (_fCreateViewWindowPending == FALSE);
  1263. VALIDATEPENDINGSTATE();
  1264. if (_bbd._psv && _IsViewMSHTML(_bbd._psv))
  1265. {
  1266. ATOMICRELEASE(_pphHistory);
  1267. SafeGetItemObject(_bbd._psv, SVGIO_BACKGROUND, IID_PPV_ARG(IPersistHistory, &_pphHistory));
  1268. }
  1269. hres = psf->CreateViewObject(_bbd._hwnd, IID_PPV_ARG(IShellView, &psvNew));
  1270. if (SUCCEEDED(hres))
  1271. {
  1272. _bbd._fCreatingViewWindow = TRUE;
  1273. IUnknown_SetSite(psvNew, _psbOuter); // SetSite for the view
  1274. _psbOuter->EnableModelessSB(FALSE);
  1275. HWND hwndViewNew = NULL;
  1276. RECT rcView;
  1277. //
  1278. // NOTES: SatoNa
  1279. //
  1280. // Notice that we explicitly call _GetViewBorderRect (non-virtual)
  1281. // instead of virtual _GetShellView, which CShellBrowser override.
  1282. // We now call thru (virtual) _pbsOuter, is this o.k.?
  1283. //
  1284. _pbsOuter->_GetViewBorderRect(&rcView);
  1285. // It is ncecessary for _bbd._pidlPending and _bbd._psvPending to both be set together.
  1286. // they're a pair
  1287. // previously _bbd._pidlPending was being set after the call to
  1288. // FileCabinet_CreateViewWindow and when messages were pumped there [NOTE: messages should not have been pumped there...]
  1289. // a redirect would be nofied in the bind status callback.
  1290. // this meant that a valid _bbd._pidlPending was actually available BUT
  1291. // then we would return and blow away that _bbd._pidlPending
  1292. //
  1293. ASSERT(_bbd._psvPending == NULL );
  1294. _bbd._psvPending = psvNew;
  1295. psvNew->AddRef();
  1296. ASSERT(_bbd._psfPending == NULL);
  1297. ASSERT(_bbd._pidlPending == NULL);
  1298. _bbd._psfPending = psf;
  1299. psf->AddRef();
  1300. _bbd._pidlPending = ILClone(pidl);
  1301. // Initialize _bbd._pidlNewShellView which will be used by GetViewStateStream
  1302. _bbd._pidlNewShellView = pidl;
  1303. _grfHLNFPending = grfHLNF;
  1304. // Start at _COMPLETE just in case the object we connect
  1305. // to doesn't notify us of ReadyState changes
  1306. //
  1307. _dwReadyStatePending = READYSTATE_COMPLETE;
  1308. // We need to cache this information here because the _dwDocFlags
  1309. // can change during the call to CreateViewWindow. This information
  1310. // is needed to determine whether or not we should stop the current
  1311. // view. If the document does not know how to navigate, then we
  1312. // stop the current view. The is needed in order to stop the
  1313. // navigation in the current view when a new navigation has started.
  1314. //
  1315. BOOL fDocCanNavigate = _dwDocFlags & DOCFLAG_DOCCANNAVIGATE;
  1316. hres = _pbsOuter->CreateViewWindow(psvNew, _bbd._psv, &rcView, &hwndViewNew);
  1317. IUnknown_SetSite(psvNew, NULL); // The view by now must have psb
  1318. _bbd._pidlNewShellView = NULL;
  1319. TraceMsg(DM_NAV, "ief NAV::%s %x %x",TEXT("_CreateNewShellView(3) Called CreateViewWindow"), psvNew, hres);
  1320. if (SUCCEEDED(hres))
  1321. {
  1322. // we defer the _PauseOrResumeView until here when we have enough
  1323. // info to know if it's a new page or not. o.w. we end up (e.g.)
  1324. // stopping bgsounds etc. on local links (nash:32270).
  1325. #ifdef NON_NATIVE_FRAMES
  1326. //
  1327. // Note (scotrobe): This was a no-op in IE5.
  1328. //
  1329. _PauseOrResumeView(_fPausedByParent);
  1330. // We stop the current view because we need to flush away any image stuff that
  1331. // is in queue so that the actual html file can get downloaded
  1332. //
  1333. _StopCurrentView();
  1334. #endif
  1335. // We can't stop the current view if the doc knows how
  1336. // to navigate. This is because in that case, the document
  1337. // in current view is the same document as the pending view.
  1338. //
  1339. if (!fDocCanNavigate)
  1340. {
  1341. _StopCurrentView();
  1342. }
  1343. _bbd._hwndViewPending = hwndViewNew;
  1344. // chrisfra - if hres == S_FALSE this (calling ActivatePendingViewAsync
  1345. // when _bbd._psv==NULL) will break async URL download
  1346. // as it will cause _bbd._psvPending to be set to NULL prematurely. this should
  1347. // be deferred until CDocObjectView::CBindStatusCallback::OnObjectAvailable
  1348. //if (hres==S_OK || _bbd._psv==NULL)
  1349. ASSERT(( hres == S_OK ) || ( hres == S_FALSE ));
  1350. if (hres == S_OK)
  1351. {
  1352. // We should activate synchronously.
  1353. //
  1354. // NOTE: This used to be ActivatePendingViewAsyc(), but that causes a
  1355. // fault if you navigated to C:\ and click A:\ as soon as it appears. This
  1356. // puts the WM_LBUTTONDOWN in FRONT of the WMC_ASYNCOPERATION message. If
  1357. // there's no disk in drive A: then a message box appears while in the
  1358. // middle of the above FileCabinet_CreateViewWindow call and we pull off
  1359. // the async activate and activate the view we're in the middle of
  1360. // creating! Don't do that.
  1361. //
  1362. fActivatePendingView = TRUE;
  1363. }
  1364. else
  1365. {
  1366. // Activation is pending.
  1367. // since the back button works as a stop on pending navigations, we
  1368. // should check that here as well.
  1369. _pbsOuter->UpdateBackForwardState();
  1370. }
  1371. }
  1372. else
  1373. {
  1374. if ( _bbd._psvPending
  1375. && !(_dwDocFlags & DOCFLAG_NAVIGATEFROMDOC)
  1376. && _IsViewMSHTML(_bbd._psvPending))
  1377. {
  1378. _fHtmlNavCanceled = TRUE;
  1379. }
  1380. else
  1381. {
  1382. _fHtmlNavCanceled = FALSE;
  1383. }
  1384. TraceMsg(DM_WARNING, "ief _CreateNewShellView psvNew->CreateViewWindow failed %x", hres);
  1385. _CancelPendingView();
  1386. }
  1387. psvNew->Release();
  1388. if (_psbOuter)
  1389. _psbOuter->EnableModelessSB(TRUE);
  1390. }
  1391. else
  1392. {
  1393. TraceMsg(TF_WARNING, "ief _BrowseTo psf->CreateViewObject failed %x", hres);
  1394. }
  1395. _fHtmlNavCanceled = FALSE;
  1396. //
  1397. // If there is any blocked async operation AND we can navigate now,
  1398. // unblock it now.
  1399. //
  1400. _MayUnblockAsyncOperation();
  1401. _bbd._fCreatingViewWindow = FALSE;
  1402. VALIDATEPENDINGSTATE();
  1403. TraceMsg(DM_WARNING, "CBB::_CNSV - Cur View MSHTML? %d Pending View MSHTML? %d",
  1404. _IsViewMSHTML(_bbd._psv), _IsViewMSHTML(_bbd._psvPending));
  1405. if (fActivatePendingView && !_IsViewMSHTML(_bbd._psvPending))
  1406. {
  1407. //
  1408. // Since _IsViewMSHTML can delegate to a marshalled interface,
  1409. // we can get re-entrancy. On re-entrancy, we can do a
  1410. // _CancelPendingView in which case _bbd._psvPending is
  1411. // no longer valid.
  1412. //
  1413. // So, we need to see if we still have _hbd._psvPending here.
  1414. //
  1415. if (_bbd._psvPending)
  1416. {
  1417. _PreActivatePendingViewAsync(); // so we match old code
  1418. hres = _pbsOuter->ActivatePendingView();
  1419. if (FAILED(hres))
  1420. TraceMsg(DM_WARNING, "CBB::_CNSV ActivatePendingView failed");
  1421. }
  1422. }
  1423. TraceMsg(DM_STARTUP, "ief _CreateNewShellView returning %x", hres);
  1424. return hres;
  1425. }
  1426. // private bind that is very loose in its bind semantics.
  1427. HRESULT IEBindToObjectForNavigate(LPCITEMIDLIST pidl, IBindCtx * pbc, IShellFolder **ppsfOut);
  1428. // this binds to the pidl folder then hands off to CreateNewShellView
  1429. // if you have anything you need to do like checking before we allow the navigate, it
  1430. // should go into _NavigateToPidl
  1431. HRESULT CBaseBrowser2::_CreateNewShellViewPidl(LPCITEMIDLIST pidl, DWORD grfHLNF, DWORD fSBSP)
  1432. {
  1433. SetNavigateState(BNS_BEGIN_NAVIGATE);
  1434. TraceMsg(DM_NAV, "ief NAV::%s %x %x",TEXT("_CreateNewShellViewPidl not same pidl"), pidl, _bbd._pidlCur);
  1435. // Check for URL-pidl?
  1436. // We will allow UI to be displayed by passing this IBindCtx to IShellFolder::BindToObject().
  1437. IBindCtx * pbc = NULL;
  1438. IShellFolder* psf;
  1439. HRESULT hres;
  1440. pbc = CreateBindCtxForUI(SAFECAST(this, IShellBrowser*)); // I'm safecasting to IUnknown. IShellBrowser is only for disambiguation.
  1441. hres = IEBindToObjectForNavigate(pidl, pbc, &psf); // If pbc is NULL, we will survive.
  1442. if (SUCCEEDED(hres))
  1443. {
  1444. hres = _CreateNewShellView(psf, pidl, grfHLNF);
  1445. TraceMsg(DM_STARTUP, "CSB::_CreateNewShellViewPidl _CreateNewShellView(3) returned %x", hres);
  1446. psf->Release();
  1447. }
  1448. else
  1449. {
  1450. // This will happen when a user tries to navigate to a directory past
  1451. // MAX_PATH by double clicking on a subdirectory in the shell.
  1452. TraceMsg(DM_TRACE, "CSB::_CreateNSVP BindToOject failed %x", hres);
  1453. }
  1454. // If _CreateNewShellView (or IEBindToObject) fails or the user cancels
  1455. // the MayOpen dialog (hres==S_FALSE), we should restore the navigation
  1456. // state to NORMAL (to stop animation).
  1457. if (FAILED(hres))
  1458. {
  1459. TraceMsg(TF_SHDNAVIGATE, "CSB::_CreateNSVP _CreateNewShellView FAILED (%x). SetNavigateState to NORMAL", hres);
  1460. SetNavigateState(BNS_NORMAL);
  1461. }
  1462. ATOMICRELEASE(pbc);
  1463. TraceMsg(DM_STARTUP, "CSB::_CreateNewShellViewPidl returning %x", hres);
  1464. return hres;
  1465. }
  1466. //
  1467. // Returns the border rectangle for the shell view.
  1468. //
  1469. HRESULT CBaseBrowser2::_GetViewBorderRect(RECT* prc)
  1470. {
  1471. _pbsOuter->_GetEffectiveClientArea(prc, NULL); // hmon?
  1472. // (derived class subtracts off border taken by all "frame" toolbars)
  1473. return S_OK;
  1474. }
  1475. //
  1476. // Returns the window rectangle for the shell view window.
  1477. //
  1478. HRESULT CBaseBrowser2::GetViewRect(RECT* prc)
  1479. {
  1480. //
  1481. // By default (when _rcBorderDoc is empty), ShellView's window
  1482. // rectangle is the same as its border rectangle.
  1483. //
  1484. _pbsOuter->_GetViewBorderRect(prc);
  1485. // Subtract document toolbar margin
  1486. prc->left += _rcBorderDoc.left;
  1487. prc->top += _rcBorderDoc.top;
  1488. prc->right -= _rcBorderDoc.right;
  1489. prc->bottom -= _rcBorderDoc.bottom;
  1490. TraceMsg(DM_UIWINDOW, "ief GetViewRect _rcBorderDoc=%x,%x,%x,%x",
  1491. _rcBorderDoc.left, _rcBorderDoc.top, _rcBorderDoc.right, _rcBorderDoc.bottom);
  1492. TraceMsg(DM_UIWINDOW, "ief GetViewRect prc=%x,%x,%x,%x",
  1493. prc->left, prc->top, prc->right, prc->bottom);
  1494. return S_OK;
  1495. }
  1496. HRESULT CBaseBrowser2::_PositionViewWindow(HWND hwnd, LPRECT prc)
  1497. {
  1498. SetWindowPos(hwnd, NULL,
  1499. prc->left, prc->top,
  1500. prc->right - prc->left,
  1501. prc->bottom - prc->top,
  1502. SWP_NOZORDER | SWP_NOACTIVATE);
  1503. return S_OK;
  1504. }
  1505. void CBaseBrowser2::_PositionViewWindowHelper(HWND hwnd, LPRECT prc)
  1506. {
  1507. if (_pbsOuter3)
  1508. _pbsOuter3->_PositionViewWindow(hwnd, prc);
  1509. else
  1510. _PositionViewWindow(hwnd, prc);
  1511. }
  1512. HRESULT CBaseBrowser2::_UpdateViewRectSize(void)
  1513. {
  1514. RECT rc;
  1515. TraceMsg(TF_SHDUIACTIVATE, "CSB::_UpdateViewRectSize called when _fDontReszeView=%d, _bbd._hwndV=%x, _bbd._hwndVP=%x",
  1516. _fDontResizeView, _bbd._hwndView, _bbd._hwndViewPending);
  1517. _pbsOuter->GetViewRect(&rc);
  1518. if (_bbd._hwndView && !_fDontResizeView)
  1519. {
  1520. TraceMsg(TF_SHDUIACTIVATE, "CSB::_UpdateViewRectSize resizing _bbd._hwndView(%x)", _bbd._hwndView);
  1521. _PositionViewWindowHelper(_bbd._hwndView, &rc);
  1522. }
  1523. if (_bbd._hwndViewPending)
  1524. {
  1525. TraceMsg(TF_SHDUIACTIVATE, "CSB::_UpdateViewRectSize resizing _bbd._hwndViewPending(%x)", _bbd._hwndViewPending);
  1526. _PositionViewWindowHelper(_bbd._hwndViewPending, &rc);
  1527. }
  1528. return S_OK;
  1529. }
  1530. UINT g_idMsgGetAuto = 0;
  1531. // this stays in shdocvw because the OC requires drop target registration
  1532. void CBaseBrowser2::_RegisterAsDropTarget()
  1533. {
  1534. // if it's okay to register and we haven't registered already
  1535. // and we've processed WM_CREATE
  1536. if (!_fNoDragDrop && !_fRegisteredDragDrop && _bbd._hwnd)
  1537. {
  1538. BOOL fAttemptRegister = _fTopBrowser ? TRUE : FALSE;
  1539. // if we're not toplevel, we still try to register
  1540. // if we have a proxy browser
  1541. if (!fAttemptRegister)
  1542. {
  1543. IShellBrowser* psb;
  1544. HRESULT hres = _pspOuter->QueryService(SID_SProxyBrowser, IID_PPV_ARG(IShellBrowser, &psb));
  1545. if (SUCCEEDED(hres))
  1546. {
  1547. fAttemptRegister = TRUE;
  1548. psb->Release();
  1549. }
  1550. }
  1551. if (fAttemptRegister)
  1552. {
  1553. HRESULT hr;
  1554. IDropTarget *pdt;
  1555. // SAFECAST(this, IDropTarget*), the hard way
  1556. hr = THR(QueryInterface(IID_PPV_ARG(IDropTarget, &pdt)));
  1557. if (SUCCEEDED(hr))
  1558. {
  1559. hr = THR(RegisterDragDrop(_bbd._hwnd, pdt));
  1560. if (SUCCEEDED(hr))
  1561. {
  1562. _fRegisteredDragDrop = TRUE;
  1563. }
  1564. pdt->Release();
  1565. }
  1566. }
  1567. }
  1568. }
  1569. void CBaseBrowser2::_UnregisterAsDropTarget()
  1570. {
  1571. if (_fRegisteredDragDrop)
  1572. {
  1573. _fRegisteredDragDrop = FALSE;
  1574. THR(RevokeDragDrop(_bbd._hwnd));
  1575. }
  1576. }
  1577. HRESULT CBaseBrowser2::OnCreate(LPCREATESTRUCT pcs)
  1578. {
  1579. HRESULT hres;
  1580. TraceMsg(DM_STARTUP, "_OnCreate called");
  1581. if (g_idMsgGetAuto == 0)
  1582. g_idMsgGetAuto = RegisterWindowMessage(TEXT("GetAutomationObject"));
  1583. hres = InitPSFInternet();
  1584. // do stuff that depends on window creation
  1585. if (SUCCEEDED(hres))
  1586. {
  1587. // this must be done AFTER the ctor so that we get virtuals right
  1588. // NOTE: only do this if we're actually creating the window, because
  1589. // the only time we SetOwner(NULL) is OnDestroy.
  1590. //
  1591. _bbd._pautoSS->SetOwner(SAFECAST(this, IShellBrowser*));
  1592. _RegisterAsDropTarget();
  1593. }
  1594. TraceMsg(DM_STARTUP, "ief OnCreate returning %d (SUCCEEDED(%x))", SUCCEEDED(hres), hres);
  1595. return SUCCEEDED(hres) ? S_OK : E_FAIL;
  1596. }
  1597. HRESULT CBaseBrowser2::OnDestroy()
  1598. {
  1599. // We're seeing some reentrancy here. If _cRefCannotNavigate is non-zero, it means we're
  1600. // in the middle of something and shouldn't destroy ourselves.
  1601. //
  1602. // Also check reentrant calls to OnDestroy().
  1603. if (_fInDestroy)
  1604. {
  1605. // Already being destroyed -- bail out.
  1606. return S_OK;
  1607. }
  1608. _fInDestroy = TRUE;
  1609. if (_cRefUIActivateSV)
  1610. {
  1611. TraceMsg(TF_WARNING,
  1612. "CBB(%x)::OnDestroy _cRefUIActivateSV(%d)!=0",
  1613. this, _cRefUIActivateSV);
  1614. // I need to defer my self-destruction.
  1615. //
  1616. _fDeferredSelfDestruction = TRUE;
  1617. return S_OK;
  1618. }
  1619. _CancelPendingView();
  1620. _pbsOuter->ReleaseShellView();
  1621. #ifdef DEBUG
  1622. // It is valid for _cRefCannotNavigate > 0 if we the system is shutting down. The reason
  1623. // for this is that we can still be processing a call to ::CreateNewShellView() when we
  1624. // the desktop recieves the WM_ENDSESSION and destroys us. In this case its ok to proceed
  1625. // with the destroy in this case, since we are logging off or rebooting anyway.
  1626. AssertMsg(_fMightBeShuttingDown || (S_FALSE == _DisableModeless()),
  1627. TEXT("CBB::OnDestroy _cRefCannotNavigate!=0 (%d)"),
  1628. _cRefCannotNavigate);
  1629. #endif
  1630. ATOMICRELEASE(_bbd._ptl);
  1631. // This should always be successful because the IDropTarget is registered
  1632. // in _OnCreate() and is the default one.
  1633. // _pdtView should have already been released in ReleaseShellView
  1634. ASSERT(_pdtView == NULL);
  1635. _UnregisterAsDropTarget();
  1636. //
  1637. // It is very important to call _bbd._pauto->SetOwner(NULL) here, which will
  1638. // remove any reference from the automation object to us. Before doing
  1639. // it, we always has cycled references and we never be released.
  1640. //
  1641. _bbd._pautoSS->SetOwner(NULL);
  1642. _bbd._hwnd = NULL;
  1643. #ifdef DEBUG
  1644. _fProcessed_WM_CLOSE = TRUE;
  1645. #endif
  1646. _DLMDestroy();
  1647. IUnknown_SetSite(_pToolbarExt, NULL); // destroy the toolbar extensions
  1648. if (_pauto)
  1649. {
  1650. IWebBrowserPriv * pWBPriv;
  1651. HRESULT hr = _pauto->QueryInterface(IID_PPV_ARG(IWebBrowserPriv, &pWBPriv));
  1652. if (SUCCEEDED(hr))
  1653. {
  1654. pWBPriv->OnClose();
  1655. pWBPriv->Release();
  1656. }
  1657. }
  1658. ATOMICRELEASE(_pHTMLDocument);
  1659. ATOMICRELEASE(_pphHistory);
  1660. return S_OK;
  1661. }
  1662. HRESULT CBaseBrowser2::NavigateToPidl(LPCITEMIDLIST pidl, DWORD grfHLNF)
  1663. {
  1664. HRESULT hr = S_OK;
  1665. LPITEMIDLIST pidlNew = (LPITEMIDLIST)pidl;
  1666. //
  1667. // Need to handle going back to an outside app - zekel 7MAY97
  1668. // i have dumped the code that did this, so now i need to put it
  1669. // into the CTravelLog implementation, so that it will be done properly
  1670. // without us. but it shouldnt be done here regardless.
  1671. //
  1672. // Remove? - with the old Travellog code
  1673. // special case hack for telling us to use the local history, not
  1674. // the global history
  1675. if (pidl && pidl != PIDL_LOCALHISTORY)
  1676. pidlNew = ILClone(pidl);
  1677. //
  1678. // Fortunately the only callers of NavigateToPidl use HLNF_NAVIGATINGBACK/FORWARD
  1679. // so that's the only mapping we need to do here.
  1680. //
  1681. DWORD dwSBSP = 0;
  1682. if (grfHLNF != (DWORD)-1)
  1683. {
  1684. if (grfHLNF & SHHLNF_WRITENOHISTORY)
  1685. dwSBSP |= SBSP_WRITENOHISTORY;
  1686. if (grfHLNF & SHHLNF_NOAUTOSELECT)
  1687. dwSBSP |= SBSP_NOAUTOSELECT;
  1688. }
  1689. if (grfHLNF & HLNF_NAVIGATINGBACK)
  1690. dwSBSP = SBSP_NAVIGATEBACK;
  1691. else if (grfHLNF & HLNF_NAVIGATINGFORWARD)
  1692. dwSBSP = SBSP_NAVIGATEFORWARD;
  1693. if (dwSBSP)
  1694. {
  1695. if (_psbOuter)
  1696. {
  1697. hr = _psbOuter->BrowseObject(pidlNew, dwSBSP); // browse will do the nav here.
  1698. }
  1699. ILFree(pidlNew);
  1700. }
  1701. else
  1702. _NavigateToPidlAsync(pidlNew, dwSBSP, FALSE); // takes ownership of the pidl
  1703. return hr;
  1704. }
  1705. // S_OK means we found at least one valid connection point
  1706. //
  1707. HRESULT GetWBConnectionPoints(IUnknown* punk, IConnectionPoint **ppcp1, IConnectionPoint **ppcp2)
  1708. {
  1709. HRESULT hres = E_FAIL;
  1710. IExpDispSupport* peds;
  1711. CConnectionPoint* pccp1 = NULL;
  1712. CConnectionPoint* pccp2 = NULL;
  1713. if (ppcp1)
  1714. *ppcp1 = NULL;
  1715. if (ppcp2)
  1716. *ppcp2 = NULL;
  1717. if (punk && SUCCEEDED(punk->QueryInterface(IID_PPV_ARG(IExpDispSupport, &peds))))
  1718. {
  1719. if (ppcp1 && SUCCEEDED(peds->FindCIE4ConnectionPoint(DIID_DWebBrowserEvents,
  1720. reinterpret_cast<CIE4ConnectionPoint**>(&pccp1))))
  1721. {
  1722. *ppcp1 = pccp1->CastToIConnectionPoint();
  1723. hres = S_OK;
  1724. }
  1725. if (ppcp2 && SUCCEEDED(peds->FindCIE4ConnectionPoint(DIID_DWebBrowserEvents2,
  1726. reinterpret_cast<CIE4ConnectionPoint**>(&pccp2))))
  1727. {
  1728. *ppcp2 = pccp2->CastToIConnectionPoint();
  1729. hres = S_OK;
  1730. }
  1731. peds->Release();
  1732. }
  1733. return hres;
  1734. }
  1735. void CBaseBrowser2::_UpdateBackForwardState()
  1736. {
  1737. if (_fTopBrowser && !_fNoTopLevelBrowser)
  1738. {
  1739. IConnectionPoint *pccp1;
  1740. IConnectionPoint *pccp2;
  1741. if (S_OK == GetWBConnectionPoints(_bbd._pautoEDS, &pccp1, &pccp2))
  1742. {
  1743. HRESULT hresT;
  1744. VARIANTARG va[2];
  1745. DISPPARAMS dp;
  1746. ITravelLog *ptl;
  1747. GetTravelLog(&ptl);
  1748. // if we've got a site or if we're trying to get to a site,
  1749. // enable the back button
  1750. BOOL fEnable = (ptl ? S_OK == ptl->GetTravelEntry(SAFECAST(this, IShellBrowser *), TLOG_BACK, NULL) : FALSE);
  1751. VARIANT_BOOL bEnable = fEnable ? VARIANT_TRUE : VARIANT_FALSE;
  1752. TraceMsg(TF_TRAVELLOG, "CBB::UpdateBackForward BACK = %d", fEnable);
  1753. // We use SHPackDispParams once instead of calling DoInvokeParams multiple times...
  1754. //
  1755. hresT = SHPackDispParams(&dp, va, 2, VT_I4, CSC_NAVIGATEBACK, VT_BOOL, bEnable);
  1756. ASSERT(S_OK==hresT);
  1757. // Removed the following EnableModelessSB(FALSE) because VB5 won't run the event handler if
  1758. // we're modal.
  1759. // _psbOuter->EnableModelessSB(FALSE);
  1760. IConnectionPoint_SimpleInvoke(pccp1, DISPID_COMMANDSTATECHANGE, &dp);
  1761. IConnectionPoint_SimpleInvoke(pccp2, DISPID_COMMANDSTATECHANGE, &dp);
  1762. fEnable = (ptl ? S_OK == ptl->GetTravelEntry(SAFECAST(this, IShellBrowser *), TLOG_FORE, NULL) : FALSE);
  1763. bEnable = fEnable ? VARIANT_TRUE : VARIANT_FALSE;
  1764. TraceMsg(TF_TRAVELLOG, "CBB::UpdateBackForward FORE = %d", fEnable);
  1765. ATOMICRELEASE(ptl);
  1766. // We know how SHPackDispParams fills in va[]
  1767. ASSERT(VT_BOOL == va[0].vt);
  1768. va[0].boolVal = bEnable;
  1769. ASSERT(VT_I4 == va[1].vt);
  1770. va[1].lVal = CSC_NAVIGATEFORWARD;
  1771. IConnectionPoint_SimpleInvoke(pccp1, DISPID_COMMANDSTATECHANGE, &dp);
  1772. IConnectionPoint_SimpleInvoke(pccp2, DISPID_COMMANDSTATECHANGE, &dp);
  1773. ATOMICRELEASE(pccp1);
  1774. ATOMICRELEASE(pccp2);
  1775. // Removed the following _psbOuter->EnableModelessSB(TRUE) because VB5 won't run the event handler if
  1776. // we're modal.
  1777. // _psbOuter->EnableModelessSB(TRUE);
  1778. }
  1779. }
  1780. }
  1781. void CBaseBrowser2::_NotifyCommandStateChange()
  1782. {
  1783. HRESULT hr;
  1784. // I'm only firing these in the toplevel case
  1785. // Why? Who cares about the frameset case
  1786. // since nobody listens to these events on
  1787. // the frameset.
  1788. //
  1789. if (_fTopBrowser && !_fNoTopLevelBrowser)
  1790. {
  1791. IConnectionPoint * pccp1;
  1792. IConnectionPoint * pccp2;
  1793. if (S_OK == GetWBConnectionPoints(_bbd._pautoEDS, &pccp1, &pccp2))
  1794. {
  1795. ASSERT(pccp1 || pccp2); // Should've gotten at least one
  1796. VARIANTARG args[2];
  1797. DISPPARAMS dp;
  1798. hr = SHPackDispParams(&dp, args, 2,
  1799. VT_I4, CSC_UPDATECOMMANDS,
  1800. VT_BOOL, FALSE);
  1801. IConnectionPoint_SimpleInvoke(pccp1, DISPID_COMMANDSTATECHANGE, &dp);
  1802. IConnectionPoint_SimpleInvoke(pccp2, DISPID_COMMANDSTATECHANGE, &dp);
  1803. ATOMICRELEASE(pccp1);
  1804. ATOMICRELEASE(pccp2);
  1805. }
  1806. }
  1807. }
  1808. LRESULT CBaseBrowser2::OnCommand(WPARAM wParam, LPARAM lParam)
  1809. {
  1810. UINT idCmd = GET_WM_COMMAND_ID(wParam, lParam);
  1811. HWND hwndControl = GET_WM_COMMAND_HWND(wParam, lParam);
  1812. if (IsInRange(idCmd, FCIDM_SHVIEWFIRST, FCIDM_SHVIEWLAST))
  1813. {
  1814. if (_bbd._hwndView)
  1815. SendMessage(_bbd._hwndView, WM_COMMAND, wParam, lParam);
  1816. else
  1817. TraceMsg(0, "view cmd id with NULL view");
  1818. /// REVIEW - how can we get FCIDM_FAVORITECMD... range if we're NOT toplevelapp?
  1819. /// REVIEW - should RecentOnCommand be done this way too?
  1820. }
  1821. return S_OK;
  1822. }
  1823. LRESULT CBaseBrowser2::OnNotify(LPNMHDR pnm)
  1824. {
  1825. // the id is from the view, probably one of the toolbar items
  1826. if (IsInRange(pnm->idFrom, FCIDM_SHVIEWFIRST, FCIDM_SHVIEWLAST))
  1827. {
  1828. if (_bbd._hwndView)
  1829. SendMessage(_bbd._hwndView, WM_NOTIFY, pnm->idFrom, (LPARAM)pnm);
  1830. }
  1831. return 0;
  1832. }
  1833. HRESULT CBaseBrowser2::OnSetFocus()
  1834. {
  1835. if (_bbd._hwndView)
  1836. {
  1837. SetFocus(_bbd._hwndView);
  1838. }
  1839. return 0;
  1840. }
  1841. #define ABOUT_HOME L"about:home"
  1842. // This function is VERY focused on achieving what the
  1843. // caller wants. That's why it has a very specific
  1844. // meaning to the return value.
  1845. BOOL IsAboutHomeOrNonAboutURL(LPITEMIDLIST pidl)
  1846. {
  1847. BOOL fIsAboutHomeOrNonAboutURL = TRUE;
  1848. WCHAR wzCur[MAX_URL_STRING];
  1849. if (pidl && SUCCEEDED(IEGetDisplayName(pidl, wzCur, SHGDN_FORPARSING)))
  1850. {
  1851. // Is it "about:home"?
  1852. if (0 != StrCmpNICW(ABOUT_HOME, wzCur, ARRAYSIZE(ABOUT_HOME) - 1))
  1853. {
  1854. // No. We also want to return TRUE if the scheme was NOT an ABOUT URL.
  1855. fIsAboutHomeOrNonAboutURL = (URL_SCHEME_ABOUT != GetUrlSchemeW(wzCur));
  1856. }
  1857. }
  1858. return fIsAboutHomeOrNonAboutURL;
  1859. }
  1860. //
  1861. // This function activate the pending view synchronously.
  1862. //
  1863. HRESULT CBaseBrowser2::ActivatePendingView(void)
  1864. {
  1865. HRESULT hres = E_FAIL;
  1866. BOOL bHadFocus;
  1867. TraceMsg(TF_SHDNAVIGATE, "CBB::ActivatePendingView called");
  1868. if (!_bbd._psvPending || !_bbd._psfPending)
  1869. {
  1870. #ifdef DEBUG
  1871. // it is valid for these to be null if we are shutting down b/c the desktop
  1872. // could have destroyed us, which would have called ::OnDestroy which calls _CancelPendingView
  1873. // which releases and nulls out _bbd._psvPending and _bbd._psfPending
  1874. ASSERT(_fMightBeShuttingDown);
  1875. #endif
  1876. goto Done;
  1877. }
  1878. #ifndef NON_NATIVE_FRAMES
  1879. IUnknown_Exec(_bbd._psvPending, &CGID_ShellDocView, SHDVID_COMPLETEDOCHOSTPASSING, 0, NULL, NULL);
  1880. #endif
  1881. #ifdef FEATURE_PICS
  1882. if (S_FALSE == IUnknown_Exec(_bbd._psvPending, &CGID_ShellDocView, SHDVID_CANACTIVATENOW, NULL, NULL, NULL))
  1883. {
  1884. hres = S_OK; // still waiting . . . but no failure.
  1885. goto DoneWait;
  1886. }
  1887. #endif
  1888. // if we are in modal loop, don't activate now
  1889. if (_cRefCannotNavigate > 0)
  1890. {
  1891. goto Done;
  1892. }
  1893. // if _cRefCannotNavigate > 0 it is possible that _hwndViewPending has not been created so this assert
  1894. // should go after the check above
  1895. ASSERT(_bbd._hwndViewPending);
  1896. // if shell view supports it, give it a chance to tell us it's not ready
  1897. // to deactivate [eg executing a script]
  1898. //
  1899. OLECMD rgCmd;
  1900. rgCmd.cmdID = SHDVID_CANDEACTIVATENOW;
  1901. rgCmd.cmdf = 0;
  1902. if (_bbd._pctView &&
  1903. SUCCEEDED(_bbd._pctView->QueryStatus(&CGID_ShellDocView, 1, &rgCmd, NULL)) &&
  1904. (rgCmd.cmdf & MSOCMDF_SUPPORTED) &&
  1905. !(rgCmd.cmdf & MSOCMDF_ENABLED))
  1906. {
  1907. //
  1908. // The DocObject that reported MSOCMDF_SUPPORTED must send
  1909. // SHDVID_DEACTIVATEMENOW when we're out of scripts or whatever so that
  1910. // we retry the activate
  1911. //
  1912. TraceMsg(DM_WARNING, "CBB::ActivatePendingView DocObject says I can't deactivate it now");
  1913. goto Done;
  1914. }
  1915. ASSERT(_bbd._psvPending);
  1916. // Prevent any navigation while we have the pointers swapped and we're in
  1917. // delicate state
  1918. _psbOuter->EnableModelessSB(FALSE);
  1919. //
  1920. // Don't play sound for the first navigation (to avoid multiple
  1921. // sounds to be played for a frame-set creation).
  1922. //
  1923. if (_bbd._psv && IsWindowVisible(_bbd._hwnd) && !(_dwSBSPQueued & SBSP_WRITENOHISTORY))
  1924. {
  1925. IEPlaySound(TEXT("ActivatingDocument"), FALSE);
  1926. }
  1927. ASSERT(_bbd._psvPending);
  1928. // NOTE: if there are any other protocols that need to not be in
  1929. // the travel log, it should probably implemented through UrlIs(URLIS_NOTRAVELLOG)
  1930. // right now, About: is the only one we care about
  1931. //
  1932. // Note that with the native frames changes, if we don't have
  1933. // a psv, we will want to call _UpdateTravelLog because that is
  1934. // where the first travel entry is added.
  1935. //
  1936. if (!(_grfHLNFPending & HLNF_CREATENOHISTORY) &&
  1937. (!_bbd._psv || IsAboutHomeOrNonAboutURL(_bbd._pidlCur))
  1938. && !_fDontUpdateTravelLog)
  1939. {
  1940. DEBUG_CODE(TCHAR szPath[INTERNET_MAX_URL_LENGTH + 1];)
  1941. DEBUG_CODE(IEGetDisplayName(_bbd._pidlCur, szPath, SHGDN_FORPARSING);)
  1942. DEBUG_CODE(TraceMsg(DM_TRACE, "CBB::ActivatePendingView (TRAVELLOG): _UpdateTravelLog called from shdocvw for %ws", szPath);)
  1943. _UpdateTravelLog();
  1944. }
  1945. // WARNING - these will only fail if the UpdateTravelLog() - zekel - 7-AUG-97
  1946. // was skipped and these bits are set.
  1947. // alanau 5-may-98 -- I still hit this assert on a script-based navigate to the same page.
  1948. // iedisp.cpp sees StrCmpW("about:blank","about:blank?http://www.microsoft.com/ie/ie40/gallery/_main.htm")
  1949. // (for example), but basesb.cpp sees two equal pidls (both "about:blank?http://...").
  1950. // Killing this assert.
  1951. // ASSERT(!_fDontAddTravelEntry);
  1952. //
  1953. // scotrobe 11-Aug-99 If the hosted document is able to
  1954. // navigate itself, _UpdateTravelLog() will never be called.
  1955. //
  1956. ASSERT((_dwDocFlags & DOCFLAG_DOCCANNAVIGATE) || !_fIsLocalAnchor);
  1957. // before we destroy the window check if it or any of its childern has focus
  1958. bHadFocus = _bbd._hwndView && (IsChildOrSelf(_bbd._hwndView, GetFocus()) == S_OK)
  1959. || _bbd._hwndViewPending && (IsChildOrSelf(_bbd._hwndViewPending, GetFocus()) == S_OK);
  1960. _pbsOuter->_SwitchActivationNow();
  1961. _psbOuter->EnableModelessSB(TRUE);
  1962. TraceMsg(DM_NAV, "CBaseBrowser2(%x)::ActivatePendingView(%x)", this, _bbd._psv);
  1963. // if some other app has focus, then don't uiactivate this navigate
  1964. // or we'll steal focus away. we'll uiactivate when we next get activated
  1965. //
  1966. // ie4.01, bug#64630 and 64329
  1967. // _fActive only gets set by WM_ACTIVATE on the TopBrowser. so for subframes
  1968. // we always defer setting the focus if they didnt have focus before navigation.
  1969. // the parent frame should set the subframe as necessary when it gets
  1970. // its UIActivate. - ReljaI 4-NOV-97
  1971. if (SVUIA_ACTIVATE_FOCUS == _bbd._uActivateState && !(_fActive || bHadFocus))
  1972. {
  1973. _bbd._uActivateState = SVUIA_INPLACEACTIVATE;
  1974. _fUIActivateOnActive = TRUE;
  1975. }
  1976. _UIActivateView(_bbd._uActivateState);
  1977. // Tell the shell's HTML window we have a new document.
  1978. if (_phtmlWS)
  1979. {
  1980. _phtmlWS->ViewActivated();
  1981. }
  1982. // this matches the _bbd._psvPending = NULL above.
  1983. // we don't put this right beside there because the
  1984. // _SwitchActivationNow could take some time, as well as the DoInvokePidl
  1985. SetNavigateState(BNS_NORMAL);
  1986. _pbsOuter->UpdateBackForwardState();
  1987. _NotifyCommandStateChange();
  1988. if (!_fNoDragDrop && _fTopBrowser)
  1989. {
  1990. ASSERT(_bbd._psv);
  1991. // _SwitchActivationNow should have already released the old _pdtView and set it to NULL
  1992. ASSERT(_pdtView == NULL);
  1993. _bbd._psv->QueryInterface(IID_PPV_ARG(IDropTarget, &_pdtView));
  1994. }
  1995. // The pending view may have a title change stored up, so fire the TitleChange.
  1996. // Also the pending view may not tell us about title changes, so simulate one.
  1997. //
  1998. if (_bbd._pszTitleCur)
  1999. {
  2000. if (_dwDocFlags & DOCFLAG_DOCCANNAVIGATE)
  2001. {
  2002. VARIANTARG varTitle;
  2003. HRESULT hrExec;
  2004. V_VT(&varTitle) = VT_BSTR;
  2005. V_BSTR(&varTitle) = SysAllocString(_bbd._pszTitleCur);
  2006. ASSERT(V_BSTR(&varTitle));
  2007. hrExec = IUnknown_Exec( _psbOuter, NULL, OLECMDID_SETTITLE, NULL, &varTitle, NULL);
  2008. VariantClear(&varTitle);
  2009. }
  2010. else
  2011. {
  2012. FireEvent_DoInvokeStringW(_bbd._pautoEDS, DISPID_TITLECHANGE, _bbd._pszTitleCur);
  2013. }
  2014. }
  2015. else if (_bbd._pidlCur)
  2016. {
  2017. WCHAR wzFullName[MAX_URL_STRING];
  2018. hres = ::IEGetNameAndFlags(_bbd._pidlCur, SHGDN_NORMAL, wzFullName, SIZECHARS(wzFullName), NULL);
  2019. if (SUCCEEDED(hres))
  2020. FireEvent_DoInvokeStringW(_bbd._pautoEDS, DISPID_TITLECHANGE, wzFullName);
  2021. }
  2022. // We must fire this event LAST because the app can shut us down
  2023. // in response to this event.
  2024. //
  2025. //
  2026. // MSWorks printing bug 104242 - Do NOT fire the NC2 event when the state is
  2027. // interactive. doing this will cause WorksCalender to print a partial document.
  2028. // Instead, we have the SetReadyState explicitly directly call FireEvent_NaviagateComplete
  2029. // and so the event will fire once the whole document has been parsed in. This
  2030. // code is matched by a bunch of event blockers in formkrnl.cxx
  2031. //
  2032. if ( GetModuleHandle(TEXT("WKSCAL.EXE")))
  2033. {
  2034. LBSTR::CString strPath;
  2035. LPTSTR pstrPath = strPath.GetBuffer( MAX_URL_STRING );
  2036. if ( strPath.GetAllocLength() < MAX_URL_STRING )
  2037. {
  2038. TraceMsg( TF_WARNING, "CBaseBrowser2::ActivatePendingView() - strPath Allocation Failed!" );
  2039. hres = E_OUTOFMEMORY;
  2040. }
  2041. else
  2042. {
  2043. hres = IEGetDisplayName( _bbd._pidlCur, pstrPath, SHGDN_FORPARSING );
  2044. // Let CString class own the buffer again.
  2045. strPath.ReleaseBuffer();
  2046. }
  2047. if ( FAILED(hres) )
  2048. {
  2049. strPath.Empty();
  2050. }
  2051. if ( GetUrlSchemeW( strPath ) == URL_SCHEME_ABOUT
  2052. || GetUrlSchemeW( strPath ) == URL_SCHEME_FILE
  2053. || GetUrlSchemeW( strPath ) == URL_SCHEME_INVALID
  2054. )
  2055. {
  2056. goto Done;
  2057. }
  2058. }
  2059. // fire the event!
  2060. FireEvent_NavigateComplete(_bbd._pautoEDS, _bbd._pautoWB2, _bbd._pidlCur, _bbd._hwnd);
  2061. // Sync up the lock icon state with CDocObjectHost
  2062. if (S_OK != IUnknown_Exec(_bbd._psv, &CGID_ShellDocView, SHDVID_FORWARDSECURELOCK, NULL, NULL, NULL))
  2063. {
  2064. // No CDocObjectHost, so we're not secure
  2065. CComVariant varLock((long) SECURELOCK_SET_UNSECURE);
  2066. if (!IsTopFrameBrowser(SAFECAST(this, IServiceProvider *), SAFECAST(this, IShellBrowser *)))
  2067. {
  2068. // we should suggest if we are not the top frame
  2069. IOleCommandTarget *pct;
  2070. if (SUCCEEDED(QueryService(SID_STopFrameBrowser, IID_PPV_ARG(IOleCommandTarget, &pct))))
  2071. {
  2072. varLock.lVal += SECURELOCK_FIRSTSUGGEST;
  2073. pct->Exec(&CGID_Explorer, SBCMDID_SETSECURELOCKICON, 0, &varLock, NULL);
  2074. pct->Release();
  2075. }
  2076. }
  2077. else
  2078. {
  2079. Exec(&CGID_Explorer, SBCMDID_SETSECURELOCKICON, 0, &varLock, NULL);
  2080. }
  2081. }
  2082. hres = S_OK;
  2083. Done:
  2084. OnReadyStateChange(NULL, READYSTATE_COMPLETE);
  2085. DoneWait:
  2086. return hres;
  2087. }
  2088. LRESULT CBaseBrowser2::_DefWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  2089. {
  2090. //
  2091. // call the UNICODE/ANSI aware DefWindowProc
  2092. //
  2093. return ::SHDefWindowProc(hwnd, uMsg, wParam, lParam);
  2094. }
  2095. void CBaseBrowser2::_ViewChange(DWORD dwAspect, LONG lindex)
  2096. {
  2097. //
  2098. // we are interested in content changes only
  2099. //
  2100. // NOTE: if we are registed for separate palette commands, then do not invalidate the colours here...
  2101. if (dwAspect & DVASPECT_CONTENT && !_fUsesPaletteCommands )
  2102. {
  2103. //
  2104. // recompute our palette
  2105. //
  2106. _ColorsDirty(BPT_UnknownPalette);
  2107. }
  2108. else
  2109. {
  2110. TraceMsg(DM_PALETTE, "cbb::_vc not interested in aspect(s) %08X", dwAspect);
  2111. }
  2112. }
  2113. void CBaseBrowser2::_ColorsDirty(BrowserPaletteType bptNew)
  2114. {
  2115. //
  2116. // if we are not currently handling palette messages then get out
  2117. //
  2118. if (_bptBrowser == BPT_DeferPaletteSupport)
  2119. {
  2120. TraceMsg(DM_PALETTE, "cbb::_cd deferring palette support");
  2121. return;
  2122. }
  2123. //
  2124. // we only handle palette changes and display changes
  2125. //
  2126. if ((bptNew != BPT_UnknownPalette) && (bptNew != BPT_UnknownDisplay))
  2127. {
  2128. AssertMsg(FALSE, TEXT("CBaseBrowser2::_ColorsDirty: invalid BPT_ constant"));
  2129. bptNew = BPT_UnknownPalette;
  2130. }
  2131. //
  2132. // if we aren't on a palettized display we don't care about palette changes
  2133. //
  2134. if ((bptNew != BPT_UnknownDisplay) && (_bptBrowser == BPT_NotPalettized))
  2135. {
  2136. TraceMsg(DM_PALETTE, "cbb::_cd not on palettized display");
  2137. return;
  2138. }
  2139. //
  2140. // if we are already handling one of these then we're done
  2141. //
  2142. if ((_bptBrowser == BPT_PaletteViewChanged) ||
  2143. (_bptBrowser == BPT_DisplayViewChanged))
  2144. {
  2145. TraceMsg(DM_PALETTE, "cbb::_cd coalesced");
  2146. return;
  2147. }
  2148. //
  2149. // unknown display implies unknown palette when the display is palettized
  2150. //
  2151. if (_bptBrowser == BPT_UnknownDisplay)
  2152. bptNew = BPT_UnknownDisplay;
  2153. //
  2154. // post ourselves a WM_QUERYNEWPALETTE so we can pile up multiple advises
  2155. // and handle them at once (we can see a lot of them sometimes...)
  2156. // NOTE: the lParam is -1 so we can tell that WE posted it and that
  2157. // NOTE: it doesn't necessarily mean we onw the foreground palette...
  2158. //
  2159. if (PostMessage(_bbd._hwnd, WM_QUERYNEWPALETTE, 0, (LPARAM) -1))
  2160. {
  2161. TraceMsg(DM_PALETTE, "cbb::_cd queued update");
  2162. //
  2163. // remember that we have already posted a WM_QUERYNEWPALETTE
  2164. //
  2165. _bptBrowser = (bptNew == BPT_UnknownPalette)?
  2166. BPT_PaletteViewChanged : BPT_DisplayViewChanged;
  2167. }
  2168. else
  2169. {
  2170. TraceMsg(DM_PALETTE, "cbb::_cd FAILED!");
  2171. //
  2172. // at least remember that the palette is stale
  2173. //
  2174. _bptBrowser = bptNew;
  2175. }
  2176. }
  2177. void CBaseBrowser2::v_PropagateMessage(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL fSend)
  2178. {
  2179. if (_bbd._hwnd)
  2180. PropagateMessage(_bbd._hwnd, uMsg, wParam, lParam, fSend);
  2181. }
  2182. void CBaseBrowser2::_DisplayChanged(WPARAM wParam, LPARAM lParam)
  2183. {
  2184. //
  2185. // forward this on to our children
  2186. //
  2187. v_PropagateMessage(WM_DISPLAYCHANGE, wParam, lParam, TRUE);
  2188. //
  2189. // and mark our colors as dirty
  2190. //
  2191. _ColorsDirty(BPT_UnknownDisplay);
  2192. }
  2193. //
  2194. // return results for _UpdateBrowserPaletteInPlace()
  2195. // S_OK : BrowserPalette was successfully updated in place
  2196. // S_FALSE : BrowserPalette is exactly the same, no need to update
  2197. // E_FAIL : Unable to update palette in place at all, caller needs to create new palette
  2198. //
  2199. HRESULT CBaseBrowser2::_UpdateBrowserPaletteInPlace(LOGPALETTE *plp)
  2200. {
  2201. if (!_hpalBrowser)
  2202. return E_FAIL;
  2203. WORD w;
  2204. if (GetObject(_hpalBrowser, sizeof(w), &w) != sizeof(w))
  2205. return E_FAIL;
  2206. if (w != plp->palNumEntries)
  2207. return E_FAIL;
  2208. if (w > 256)
  2209. return E_FAIL;
  2210. //
  2211. // GDI marks a palette as dirty if you update its colors
  2212. // only replace the entries if the colors are actually different
  2213. // this prevents excessive flashing
  2214. //
  2215. PALETTEENTRY ape[256];
  2216. if (GetPaletteEntries(_hpalBrowser, 0, w, ape) != w)
  2217. return E_FAIL;
  2218. if (memcmp(ape, plp->palPalEntry, w * sizeof(PALETTEENTRY)) == 0)
  2219. {
  2220. TraceMsg(DM_PALETTE, "cbb::_ubpip %08x already had view object's colors", _hpalBrowser);
  2221. return S_FALSE;
  2222. }
  2223. // make sure we don't reuse the global halftone palette that we are reusing across shdocvw....
  2224. // do this after we've done the colour match
  2225. if ( _hpalBrowser == g_hpalHalftone )
  2226. {
  2227. return E_FAIL;
  2228. }
  2229. //
  2230. // actually set up the colors
  2231. //
  2232. if (SetPaletteEntries(_hpalBrowser, 0, plp->palNumEntries,
  2233. plp->palPalEntry) != plp->palNumEntries)
  2234. {
  2235. return E_FAIL;
  2236. }
  2237. TraceMsg(DM_PALETTE, "cbb::_ubpip updated %08x with view object's colors", _hpalBrowser);
  2238. return S_OK;
  2239. }
  2240. void CBaseBrowser2::_RealizeBrowserPalette(BOOL fBackground)
  2241. {
  2242. HPALETTE hpalRealize;
  2243. //
  2244. // get a palette to realize
  2245. //
  2246. if (_hpalBrowser)
  2247. {
  2248. TraceMsg(DM_PALETTE, "cbb::_rbp realizing %08x", _hpalBrowser);
  2249. hpalRealize = _hpalBrowser;
  2250. }
  2251. else
  2252. {
  2253. TraceMsg(DM_PALETTE, "cbb::_rbp realizing DEFAULT_PALETTE");
  2254. hpalRealize = (HPALETTE) GetStockObject(DEFAULT_PALETTE);
  2255. }
  2256. if ( !_fOwnsPalette && !fBackground )
  2257. {
  2258. // NOTE: if we don't think we own the foreground palette, and we
  2259. // NOTE: are being told to realize in the foreground, then ignore
  2260. // NOTE: it because they are wrong...
  2261. fBackground = TRUE;
  2262. }
  2263. //
  2264. // get a DC to realize on and select our palette
  2265. //
  2266. HDC hdc = GetDC(_bbd._hwnd);
  2267. if (hdc)
  2268. {
  2269. HPALETTE hpalOld = SelectPalette(hdc, hpalRealize, fBackground);
  2270. if (hpalOld)
  2271. {
  2272. //
  2273. // we don't paint any palettized stuff ourselves we're just a frame
  2274. // eg. we don't need to repaint here if the realize returns nonzero
  2275. //
  2276. RealizePalette(hdc);
  2277. //
  2278. // since we create and delete our palette alot, don't leave it selected
  2279. //
  2280. SelectPalette(hdc, hpalOld, TRUE);
  2281. }
  2282. ReleaseDC(_bbd._hwnd, hdc);
  2283. }
  2284. }
  2285. void CBaseBrowser2::_PaletteChanged(WPARAM wParam, LPARAM lParam)
  2286. {
  2287. TraceMsg(DM_PALETTE, "cbb::_pc (%08X, %08X, %08X) begins -----------------------", this, wParam, lParam);
  2288. //
  2289. // cdturner: 08/03/97
  2290. // we think that we currently own the foregorund palette, we need to make sure that
  2291. // the window that just realized in the foreground (and thus caused the system
  2292. // to generate the WM_PALETTECHANGED) was us, otherwise, we no longer own the
  2293. // palette
  2294. //
  2295. if ( _fOwnsPalette )
  2296. {
  2297. // by default we do not own it.
  2298. _fOwnsPalette = FALSE;
  2299. // the wParam hwnd we get is the top-level window that cause it, so we need to walk the window
  2300. // chain to find out if it is one of our parents...
  2301. // start at _bbd._hwnd (incase we are the top-level :-))
  2302. HWND hwndParent = _bbd._hwnd;
  2303. while ( hwndParent != NULL )
  2304. {
  2305. if ( hwndParent == (HWND) wParam )
  2306. {
  2307. // we caused it, so therefore we must still own it...
  2308. _fOwnsPalette = TRUE;
  2309. break;
  2310. }
  2311. hwndParent = GetParent( hwndParent );
  2312. }
  2313. }
  2314. //
  2315. // should we realize now? (see _QueryNewPalette to understand _bptBrowser)
  2316. //
  2317. // NOTE: we realize in the background here on purpose! This helps us be
  2318. // compatible with Netscape plugins etc that think they can own the
  2319. // palette from inside the browser.
  2320. //
  2321. if (((HWND)wParam != _bbd._hwnd) && (_bptBrowser == BPT_Normal))
  2322. _RealizeBrowserPalette(TRUE);
  2323. //
  2324. // always forward the changes to the current view
  2325. // let the toolbars know too
  2326. //
  2327. if (_bbd._hwndView)
  2328. TraceMsg(DM_PALETTE, "cbb::_pc forwarding to view window %08x", _bbd._hwndView);
  2329. _pbsOuter->_SendChildren(_bbd._hwndView, TRUE, WM_PALETTECHANGED, wParam, lParam); // SendMessage
  2330. TraceMsg(DM_PALETTE, "cbb::_pc (%08X) ends -------------------------", this);
  2331. }
  2332. BOOL CBaseBrowser2::_QueryNewPalette()
  2333. {
  2334. BrowserPaletteType bptNew;
  2335. HPALETTE hpalNew = NULL;
  2336. BOOL fResult = TRUE;
  2337. BOOL fSkipRealize = FALSE;
  2338. HDC hdc;
  2339. TraceMsg(DM_PALETTE, "cbb::_qnp (%08X) begins ==================================", this);
  2340. TryAgain:
  2341. switch (_bptBrowser)
  2342. {
  2343. case BPT_Normal:
  2344. TraceMsg(DM_PALETTE, "cbb::_qnp - normal realization");
  2345. //
  2346. // Normal Realization: realize _hpalBrowser in the foreground
  2347. //
  2348. // avoid realzing the palette into the display if we've been asked not to...
  2349. if ( !fSkipRealize )
  2350. _RealizeBrowserPalette(FALSE);
  2351. break;
  2352. case BPT_ShellView:
  2353. TraceMsg(DM_PALETTE, "cbb::_qnp - forwarding to shell view");
  2354. //
  2355. // Win95 Explorer-compatible: forward the query to the shell view
  2356. //
  2357. if (_bbd._hwndView && SendMessage(_bbd._hwndView, WM_QUERYNEWPALETTE, 0, 0))
  2358. break;
  2359. TraceMsg(DM_PALETTE, "cbb::_qnp - no shell view or view didn't answer");
  2360. //
  2361. // we only manage our palette as a toplevel app
  2362. //
  2363. //
  2364. // the view didn't handle it; fall through to use a generic palette
  2365. //
  2366. UseGenericPalette:
  2367. TraceMsg(DM_PALETTE, "cbb::_qnp - using generic palette");
  2368. //
  2369. // Use a Halftone Palette for the device
  2370. //
  2371. hpalNew = g_hpalHalftone;
  2372. bptNew = BPT_Normal;
  2373. goto UseThisPalette;
  2374. case BPT_UnknownPalette:
  2375. case BPT_PaletteViewChanged:
  2376. TraceMsg(DM_PALETTE, "cbb::_qnp - computing palette");
  2377. //
  2378. // Undecided: try to use IViewObject::GetColorSet to compose a palette
  2379. //
  2380. LOGPALETTE *plp;
  2381. HRESULT hres;
  2382. // default to forwarding to the view if something fails along the way
  2383. hpalNew = NULL;
  2384. bptNew = BPT_ShellView;
  2385. //
  2386. // if we have a view object then try to get its color set
  2387. //
  2388. if (!_pvo)
  2389. {
  2390. TraceMsg(DM_PALETTE, "cbb::_qnp - no view object");
  2391. goto UseGenericPalette;
  2392. }
  2393. plp = NULL;
  2394. hres = _pvo->GetColorSet(DVASPECT_CONTENT, -1, NULL, NULL, NULL, &plp);
  2395. if (FAILED(hres))
  2396. {
  2397. TraceMsg(DM_PALETTE, "cbb::_qnp - view object's GetColorSet failed");
  2398. goto UseThisPalette;
  2399. }
  2400. //
  2401. // either a null color set or S_FALSE mean the view object doesn't care
  2402. //
  2403. if (!plp)
  2404. hres = S_FALSE;
  2405. if (hres != S_FALSE)
  2406. {
  2407. //
  2408. // can we reuse the current palette object?
  2409. //
  2410. HRESULT hrLocal = _UpdateBrowserPaletteInPlace(plp);
  2411. if (FAILED( hrLocal ))
  2412. {
  2413. TraceMsg(DM_PALETTE, "cbb::_qnp - creating new palette for view object's colors");
  2414. hpalNew = CreatePalette(plp);
  2415. }
  2416. else
  2417. {
  2418. hpalNew = _hpalBrowser;
  2419. // NOTE: if we got back the same palette, don't bother realizing it into the foreground.
  2420. // NOTE: this has the (desirable) side effect of stops us flashing the display when a
  2421. // NOTE: control on a page has (wrongly) realized its own palette...
  2422. if ( hrLocal == S_FALSE )
  2423. {
  2424. // ASSERT( GetActiveWindow() == _bbd._hwnd );
  2425. fSkipRealize = TRUE;
  2426. }
  2427. }
  2428. //
  2429. // did we succeed at setting up a palette?
  2430. //
  2431. if (hpalNew)
  2432. {
  2433. TraceMsg(DM_PALETTE, "cbb::_qnp - palette is ready to use");
  2434. bptNew = BPT_Normal;
  2435. }
  2436. else
  2437. {
  2438. TraceMsg(DM_PALETTE, "cbb::_qnp - failed to create palette");
  2439. }
  2440. }
  2441. //
  2442. // free the logical palette from the GetColorSet above
  2443. //
  2444. if (plp)
  2445. CoTaskMemFree(plp);
  2446. //
  2447. // if the view object responded that it didn't care then pick a palette
  2448. //
  2449. if (hres == S_FALSE)
  2450. {
  2451. TraceMsg(DM_PALETTE, "cbb::_qnp - view object doesn't care");
  2452. goto UseGenericPalette;
  2453. }
  2454. //
  2455. // fall through to use the palette we decided on
  2456. //
  2457. UseThisPalette:
  2458. //
  2459. // we get here when we've decided on a new palette strategy
  2460. //
  2461. TraceMsg(DM_PALETTE, "cbb::_qnp - chose palette %08x", hpalNew);
  2462. //
  2463. // do we have a new palette object to use?
  2464. //
  2465. if (hpalNew != _hpalBrowser)
  2466. {
  2467. if (_hpalBrowser && _hpalBrowser != g_hpalHalftone)
  2468. {
  2469. TraceMsg(DM_PALETTE, "cbb::_qnp - deleting old palette %08x", _hpalBrowser);
  2470. DeletePalette(_hpalBrowser);
  2471. }
  2472. _hpalBrowser = hpalNew;
  2473. }
  2474. //
  2475. // notify the hosted object that we just changed the palette......
  2476. //
  2477. if ( _bbd._pctView )
  2478. {
  2479. VARIANTARG varIn = {0};
  2480. varIn.vt = VT_I4;
  2481. varIn.intVal = DISPID_AMBIENT_PALETTE;
  2482. _bbd._pctView->Exec( &CGID_ShellDocView, SHDVID_AMBIENTPROPCHANGE, 0, &varIn, NULL );
  2483. }
  2484. //
  2485. // now loop back and use this new palette strategy
  2486. //
  2487. _bptBrowser = bptNew;
  2488. goto TryAgain;
  2489. case BPT_UnknownDisplay:
  2490. case BPT_DisplayViewChanged:
  2491. case BPT_DeferPaletteSupport:
  2492. TraceMsg(DM_PALETTE, "cbb::_qnp - unknown display");
  2493. //
  2494. // Unknown Display: decide whether we need palette support or not
  2495. //
  2496. hdc = GetDC(NULL);
  2497. if (hdc)
  2498. {
  2499. bptNew = (GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE)?
  2500. BPT_UnknownPalette : BPT_NotPalettized;
  2501. ReleaseDC(NULL, hdc);
  2502. }
  2503. //
  2504. // Set the new mode and branch accordingly
  2505. // NOTE: we don't do a UseThisPalette here because it is still unknown
  2506. //
  2507. if (hdc && (_bptBrowser = bptNew) == BPT_UnknownPalette)
  2508. goto TryAgain;
  2509. TraceMsg(DM_PALETTE, "cbb::_qnp - not in palettized display mode");
  2510. //
  2511. // fall through to non-palette case
  2512. //
  2513. case BPT_NotPalettized:
  2514. //
  2515. // Not in Palettized Mode: do nothing
  2516. //
  2517. // if we just switched from a palettized mode then free our palette
  2518. //
  2519. if (_hpalBrowser)
  2520. {
  2521. TraceMsg(DM_PALETTE, "cbb::_qnp - old palette still lying around");
  2522. hpalNew = NULL;
  2523. bptNew = BPT_NotPalettized;
  2524. goto UseThisPalette;
  2525. }
  2526. //
  2527. // and don't do anything else
  2528. //
  2529. fResult = FALSE;
  2530. break;
  2531. default:
  2532. TraceMsg(DM_PALETTE, "cbb::_qnp - invalid BPT_ state!");
  2533. //
  2534. // we should never get here
  2535. //
  2536. ASSERT(FALSE);
  2537. _bptBrowser = BPT_UnknownDisplay;
  2538. goto TryAgain;
  2539. }
  2540. TraceMsg(DM_PALETTE, "cbb::_qnp (%08X) ends ====================================", this);
  2541. return fResult;
  2542. }
  2543. HRESULT CBaseBrowser2::_TryShell2Rename(IShellView* psv, LPCITEMIDLIST pidlNew)
  2544. {
  2545. HRESULT hres = E_FAIL;
  2546. if (EVAL(psv)) // Winstone once found it to be NULL.
  2547. {
  2548. // ? - overloading the semantics of IShellExtInit
  2549. IPersistFolder* ppf;
  2550. hres = psv->QueryInterface(IID_PPV_ARG(IPersistFolder, &ppf));
  2551. if (SUCCEEDED(hres))
  2552. {
  2553. hres = ppf->Initialize(pidlNew);
  2554. if (SUCCEEDED(hres))
  2555. {
  2556. // we need to update what we're pointing to
  2557. LPITEMIDLIST pidl = ILClone(pidlNew);
  2558. if (pidl)
  2559. {
  2560. if (IsSameObject(psv, _bbd._psv))
  2561. {
  2562. ASSERT(_bbd._pidlCur);
  2563. ILFree(_bbd._pidlCur);
  2564. _bbd._pidlCur = pidl;
  2565. // If the current pidl is renamed, we need to fire a
  2566. // TITLECHANGE event. We don't need to do this in the
  2567. // pending case because the NavigateComplete provides
  2568. // a way to get the title.
  2569. //
  2570. WCHAR wzFullName[MAX_URL_STRING];
  2571. ::IEGetNameAndFlags(_bbd._pidlCur, SHGDN_NORMAL, wzFullName, SIZECHARS(wzFullName), NULL);
  2572. FireEvent_DoInvokeStringW(_bbd._pautoEDS, DISPID_TITLECHANGE, wzFullName);
  2573. }
  2574. else if (IsSameObject(psv, _bbd._psvPending))
  2575. {
  2576. ASSERT(_bbd._pidlPending);
  2577. ILFree(_bbd._pidlPending);
  2578. _bbd._pidlPending = pidl;
  2579. }
  2580. else
  2581. {
  2582. // It may be possible to get here during _MayPlayTransition!
  2583. //
  2584. ASSERT(!_bbd._psvPending); // this should be the case if we get here
  2585. ASSERT(FALSE); // we should never get here or we have a problem
  2586. }
  2587. }
  2588. }
  2589. ppf->Release();
  2590. }
  2591. }
  2592. return hres;
  2593. }
  2594. HRESULT CBaseBrowser2::OnSize(WPARAM wParam)
  2595. {
  2596. if (wParam != SIZE_MINIMIZED)
  2597. {
  2598. _pbsOuter->v_ShowHideChildWindows(FALSE);
  2599. }
  2600. return S_OK;
  2601. }
  2602. BOOL CBaseBrowser2::v_OnSetCursor(LPARAM lParam)
  2603. {
  2604. if (_fNavigate || _fDescendentNavigate)
  2605. {
  2606. switch (LOWORD(lParam))
  2607. {
  2608. case HTBOTTOM:
  2609. case HTTOP:
  2610. case HTLEFT:
  2611. case HTRIGHT:
  2612. case HTBOTTOMLEFT:
  2613. case HTBOTTOMRIGHT:
  2614. case HTTOPLEFT:
  2615. case HTTOPRIGHT:
  2616. break;
  2617. default:
  2618. SetCursor(LoadCursor(NULL, IDC_APPSTARTING));
  2619. return TRUE;
  2620. }
  2621. }
  2622. else
  2623. {
  2624. if (GetTickCount() < _dwStartingAppTick + STARTING_APP_DURATION)
  2625. {
  2626. SetCursor(LoadCursor(NULL, IDC_APPSTARTING));
  2627. return TRUE;
  2628. }
  2629. }
  2630. return FALSE;
  2631. }
  2632. const SA_BSTRGUID s_sstrSearchFlags = {
  2633. 38 * SIZEOF(WCHAR),
  2634. L"{265b75c1-4158-11d0-90f6-00c04fd497ea}"
  2635. };
  2636. #define PROPERTY_VALUE_SEARCHFLAGS ((BSTR)s_sstrSearchFlags.wsz)
  2637. LRESULT CBaseBrowser2::_OnGoto(void)
  2638. {
  2639. TraceMsg(TF_SHDNAVIGATE, "CBB::_OnGoto called");
  2640. //
  2641. // If we can't navigate right now, postpone it by restoring _uAction
  2642. // and don't free pidlQueued. Subsequent _MayUnblockAsyncOperation call
  2643. // will post WMC_ASYNCOPERATION (if we can navigate) and we come here
  2644. // again.
  2645. //
  2646. if (!_CanNavigate())
  2647. {
  2648. TraceMsg(TF_SHDNAVIGATE, "CBB::_OnGoto can't do it now. Postpone!");
  2649. _uActionQueued = ASYNCOP_GOTO;
  2650. return S_FALSE;
  2651. }
  2652. LPITEMIDLIST pidl = _pidlQueued;
  2653. DWORD dwSBSP = _dwSBSPQueued;
  2654. _dwSBSPQueued = 0;
  2655. _pidlQueued = NULL;
  2656. if (pidl && PIDL_NOTHING != pidl)
  2657. {
  2658. DWORD grfHLNF = 0;
  2659. if (dwSBSP & SBSP_WRITENOHISTORY)
  2660. {
  2661. grfHLNF |= SHHLNF_WRITENOHISTORY;
  2662. }
  2663. if (dwSBSP & SBSP_NOAUTOSELECT)
  2664. {
  2665. grfHLNF |= SHHLNF_NOAUTOSELECT;
  2666. }
  2667. if (PIDL_LOCALHISTORY == pidl)
  2668. {
  2669. pidl = NULL;
  2670. // For beta2 we need to do a better job mapping SBSP to HLNF values.
  2671. // For beta1, this is the only case that's busted.
  2672. //
  2673. // This problem stems from converting _NavigateToPidl in ::NavigateToPidl
  2674. // into a call to the Async version
  2675. //
  2676. if (dwSBSP & SBSP_NAVIGATEBACK)
  2677. grfHLNF = HLNF_NAVIGATINGBACK;
  2678. else if (dwSBSP & SBSP_NAVIGATEFORWARD)
  2679. grfHLNF = HLNF_NAVIGATINGFORWARD;
  2680. }
  2681. else if (dwSBSP == (DWORD)-1)
  2682. {
  2683. // Same problem as above
  2684. //
  2685. // This problem stems from converting _NavigateToPidl in ::NavigateToTLItem
  2686. // into a call to the Async version
  2687. //
  2688. grfHLNF = (DWORD)-1;
  2689. }
  2690. else
  2691. {
  2692. if (dwSBSP & SBSP_REDIRECT)
  2693. grfHLNF |= HLNF_CREATENOHISTORY;
  2694. {
  2695. IWebBrowser2 *pWB2;
  2696. BOOL bAllow = ((dwSBSP & SBSP_ALLOW_AUTONAVIGATE) ? TRUE : FALSE);
  2697. if (bAllow)
  2698. grfHLNF |= HLNF_ALLOW_AUTONAVIGATE;
  2699. if (SUCCEEDED(_pspOuter->QueryService(SID_SHlinkFrame, IID_PPV_ARG(IWebBrowser2, &pWB2))))
  2700. {
  2701. if (pWB2)
  2702. {
  2703. VARIANT v = {0}; // for failure of below call
  2704. pWB2->GetProperty(PROPERTY_VALUE_SEARCHFLAGS, &v);
  2705. if (v.vt == VT_I4)
  2706. {
  2707. v.lVal &= (~ 0x00000001); // Clear the allow flag before we try to set it.
  2708. v.lVal |= (bAllow ? 0x01 : 0x00);
  2709. }
  2710. else
  2711. {
  2712. VariantClear(&v);
  2713. v.vt = VT_I4;
  2714. v.lVal = (bAllow ? 0x01 : 0x00);
  2715. }
  2716. pWB2->PutProperty(PROPERTY_VALUE_SEARCHFLAGS, v);
  2717. pWB2->Release();
  2718. }
  2719. }
  2720. }
  2721. }
  2722. TraceMsg(DM_NAV, "ief NAV::%s %x %x",TEXT("_OnGoto called calling _NavigateToPidl"), pidl, _bbd._pidlCur);
  2723. _pbsOuter->_NavigateToPidl(pidl, (DWORD)grfHLNF, dwSBSP);
  2724. }
  2725. else
  2726. {
  2727. // wParam=NULL means canceling the navigation.
  2728. TraceMsg(DM_NAV, "NAV::_OnGoto calling _CancelPendingView");
  2729. _CancelPendingView();
  2730. if (PIDL_NOTHING == pidl)
  2731. {
  2732. // If we're being told to navigate to nothing, go there
  2733. //
  2734. // What should we do with the history??
  2735. //
  2736. _pbsOuter->ReleaseShellView();
  2737. }
  2738. else if (!_bbd._pidlCur)
  2739. {
  2740. //
  2741. // If the very first navigation failed, navigate to
  2742. // a local html file so that the user will be able
  2743. // to View->Options dialog.
  2744. //
  2745. TCHAR szPath[MAX_PATH]; // This is always local
  2746. HRESULT hresT = _GetStdLocation(szPath, ARRAYSIZE(szPath), DVIDM_GOLOCALPAGE);
  2747. if (FAILED(hresT) || !PathFileExists(szPath))
  2748. {
  2749. StrCpyN(szPath, TEXT("shell:Desktop"), ARRAYSIZE(szPath));
  2750. }
  2751. BSTR bstr = SysAllocStringT(szPath);
  2752. if (bstr)
  2753. {
  2754. TraceMsg(TF_SHDNAVIGATE, "CBB::_OnGoto Calling _bbd._pauto->Navigate(%s)", szPath);
  2755. _bbd._pautoWB2->Navigate(bstr,NULL,NULL,NULL,NULL);
  2756. SysFreeString(bstr);
  2757. }
  2758. }
  2759. }
  2760. _FreeQueuedPidl(&pidl);
  2761. return 0;
  2762. }
  2763. void CBaseBrowser2::_FreeQueuedPidl(LPITEMIDLIST* ppidl)
  2764. {
  2765. if (*ppidl && PIDL_NOTHING != *ppidl)
  2766. {
  2767. ILFree(*ppidl);
  2768. }
  2769. *ppidl = NULL;
  2770. }
  2771. HRESULT CBaseBrowser2::OnFrameWindowActivateBS(BOOL fActive)
  2772. {
  2773. BOOL fOldActive = _fActive;
  2774. if (_pact)
  2775. {
  2776. TraceMsg(TF_SHDUIACTIVATE, "OnFrameWindowActivateBS(%d)", fActive);
  2777. _pact->OnFrameWindowActivate(fActive);
  2778. }
  2779. _fActive = fActive;
  2780. if (fActive && !fOldActive && _fUIActivateOnActive)
  2781. {
  2782. _fUIActivateOnActive = FALSE;
  2783. _UIActivateView(SVUIA_ACTIVATE_FOCUS);
  2784. }
  2785. return S_OK;
  2786. }
  2787. LRESULT CBaseBrowser2::WndProcBS(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  2788. {
  2789. if (uMsg == g_uMsgFileOpened)
  2790. {
  2791. AppStarted();
  2792. return 0;
  2793. }
  2794. switch(uMsg)
  2795. {
  2796. #ifdef DEBUG
  2797. // compile time assert to make sure we don't use these msgs
  2798. // here since we must allow these to go to the subclasses
  2799. case CWM_GLOBALSTATECHANGE:
  2800. case CWM_FSNOTIFY:
  2801. case WMC_ACTIVATE:
  2802. break;
  2803. case WM_QUERYENDSESSION:
  2804. // assume we are going to be shutting down (if we aren't, we unset this during the
  2805. // WM_ENDSESSION message)
  2806. _fMightBeShuttingDown = TRUE;
  2807. goto DoDefault; // act like we didn't handle this msg
  2808. break;
  2809. case WM_ENDSESSION:
  2810. // the wParam tells us if the session is being ended or not
  2811. _fMightBeShuttingDown = (BOOL)wParam;
  2812. return 0;
  2813. break;
  2814. #endif
  2815. // UGLY: Win95/NT4 shell DefView code sends this msg and does not deal
  2816. // with the failure case. other ISVs do the same so this needs to stay forever
  2817. case CWM_GETISHELLBROWSER:
  2818. return (LRESULT)_psbOuter; // not ref counted!
  2819. // WM_COPYDATA is used to implement inter-window target'ed navigation
  2820. // Copy data contains target, URL, postdata and referring URL
  2821. case WM_COPYDATA:
  2822. return (LRESULT)FALSE;
  2823. case WMC_ASYNCOPERATION:
  2824. {
  2825. UINT uAction = _uActionQueued;
  2826. _uActionQueued = ASYNCOP_NIL;
  2827. switch(uAction)
  2828. {
  2829. case ASYNCOP_GOTO:
  2830. _OnGoto();
  2831. break;
  2832. case ASYNCOP_ACTIVATEPENDING:
  2833. VALIDATEPENDINGSTATE();
  2834. if (_bbd._psvPending) // paranoia
  2835. {
  2836. if (FAILED(_pbsOuter->ActivatePendingView()) && _cRefCannotNavigate > 0)
  2837. {
  2838. _uActionQueued = ASYNCOP_ACTIVATEPENDING; // retry activation
  2839. }
  2840. }
  2841. break;
  2842. case ASYNCOP_CANCELNAVIGATION:
  2843. _CancelPendingNavigation();
  2844. break;
  2845. case ASYNCOP_NIL:
  2846. break;
  2847. default:
  2848. ASSERT(0);
  2849. break;
  2850. }
  2851. }
  2852. break;
  2853. case WMC_DELAYEDDDEEXEC:
  2854. return IEDDE_RunDelayedExecute();
  2855. break;
  2856. case WM_SIZE:
  2857. _pbsOuter->OnSize(wParam);
  2858. break;
  2859. #ifdef PAINTINGOPTS
  2860. case WM_WINDOWPOSCHANGING:
  2861. // Let's not waste any time blitting bits around, the viewer window
  2862. // is really the guy that has the content so when it resizes itself
  2863. // it can decide if it needs to blt or not. This also makes resizing
  2864. // look nicer.
  2865. ((LPWINDOWPOS)lParam)->flags |= SWP_NOCOPYBITS;
  2866. goto DoDefault;
  2867. #endif
  2868. case WM_ERASEBKGND:
  2869. if (!_bbd._hwndView)
  2870. goto DoDefault;
  2871. goto DoDefault;
  2872. case WM_SETFOCUS:
  2873. return _pbsOuter->OnSetFocus();
  2874. case WM_DISPLAYCHANGE:
  2875. _DisplayChanged(wParam, lParam);
  2876. break;
  2877. case WM_PALETTECHANGED:
  2878. _PaletteChanged(wParam, lParam);
  2879. break;
  2880. case WM_QUERYNEWPALETTE:
  2881. // we always pass -1 as the LParam to show that we posted it to ourselves...
  2882. if ( lParam != 0xffffffff )
  2883. {
  2884. // otherwise, it looks like the system or our parent has just sent a real honest to God,
  2885. // system WM_QUERYNEWPALETTE, so we now own the Foreground palette and we have a license to
  2886. // to SelectPalette( hpal, FALSE );
  2887. _fOwnsPalette = TRUE;
  2888. }
  2889. return _QueryNewPalette();
  2890. case WM_SYSCOLORCHANGE:
  2891. case WM_ENTERSIZEMOVE:
  2892. case WM_EXITSIZEMOVE:
  2893. case WM_WININICHANGE:
  2894. case WM_FONTCHANGE:
  2895. v_PropagateMessage(uMsg, wParam, lParam, TRUE);
  2896. break;
  2897. case WM_PRINT:
  2898. // Win95 explorer did this
  2899. if (_bbd._hwndView)
  2900. SendMessage(_bbd._hwndView, uMsg, wParam, lParam);
  2901. break;
  2902. #ifdef DEBUG
  2903. case WM_ACTIVATE:
  2904. // do *not* do any toolbar stuff here. it will mess up the desktop.
  2905. // override does that in shbrows2.cpp
  2906. TraceMsg(DM_FOCUS, "cbb.wpbs(WM_ACT): => default");
  2907. goto DoDefault;
  2908. #endif
  2909. case WM_SETCURSOR:
  2910. if (v_OnSetCursor(lParam))
  2911. return TRUE;
  2912. goto DoDefault;
  2913. case WM_TIMER:
  2914. if (wParam == IDT_STARTING_APP_TIMER)
  2915. {
  2916. AppStarted();
  2917. return 0;
  2918. }
  2919. goto DoDefault;
  2920. case WM_CREATE:
  2921. if (S_OK != _pbsOuter->OnCreate((LPCREATESTRUCT)lParam))
  2922. {
  2923. _pbsOuter->OnDestroy();
  2924. return -1;
  2925. }
  2926. g_uMsgFileOpened = RegisterWindowMessage(SH_FILEOPENED);
  2927. return 0;
  2928. case WM_NOTIFY:
  2929. return _pbsOuter->OnNotify((LPNMHDR)lParam);
  2930. case WM_COMMAND:
  2931. _pbsOuter->OnCommand(wParam, lParam);
  2932. break;
  2933. case WM_DESTROY:
  2934. _pbsOuter->OnDestroy();
  2935. break;
  2936. case WMC_IEHARD_NAVWARNING:
  2937. _ShowIEHardNavWarning();
  2938. break;
  2939. default:
  2940. if (uMsg == g_idMsgGetAuto)
  2941. {
  2942. //
  2943. // According to LauraBu, using WM_GETOBJECT for our private
  2944. // purpose will work, but will dramatically slow down
  2945. // accessibility apps unless we actually implement one of
  2946. // accessibility interfaces. Therefore, we use a registered
  2947. // message to get the automation/frame interface out of
  2948. // IE/Nashvile frame. (SatoNa)
  2949. //
  2950. IUnknown* punk;
  2951. if (SUCCEEDED(_bbd._pautoSS->QueryInterface(*(IID*)wParam, (void **)&punk)))
  2952. return (LRESULT)punk; // Note that it's AddRef'ed by QI.
  2953. return 0;
  2954. }
  2955. else if (uMsg == GetWheelMsg())
  2956. {
  2957. // Forward the mouse wheel message on to the view window
  2958. if (_bbd._hwndView)
  2959. {
  2960. PostMessage(_bbd._hwndView, uMsg, wParam, lParam);
  2961. return 1;
  2962. }
  2963. // Fall through...
  2964. }
  2965. DoDefault:
  2966. return _DefWindowProc(hwnd, uMsg, wParam, lParam);
  2967. }
  2968. return 0;
  2969. }
  2970. // *** IOleWindow methods ***
  2971. HRESULT CBaseBrowser2::GetWindow(HWND * lphwnd)
  2972. {
  2973. *lphwnd = _bbd._hwnd;
  2974. return S_OK;
  2975. }
  2976. HRESULT CBaseBrowser2::GetViewWindow(HWND * lphwnd)
  2977. {
  2978. *lphwnd = _bbd._hwndView;
  2979. return S_OK;
  2980. }
  2981. HRESULT CBaseBrowser2::ContextSensitiveHelp(BOOL fEnterMode)
  2982. {
  2983. return E_NOTIMPL;
  2984. }
  2985. // *** IShellBrowser methods *** (same as IOleInPlaceFrame)
  2986. HRESULT CBaseBrowser2::InsertMenusSB(HMENU hmenuShared, LPOLEMENUGROUPWIDTHS lpMenuWidths)
  2987. {
  2988. return S_OK;
  2989. }
  2990. HRESULT CBaseBrowser2::SetMenuSB(HMENU hmenuShared, HOLEMENU holemenuReserved, HWND hwndActiveObject)
  2991. {
  2992. return S_OK;
  2993. }
  2994. /*----------------------------------------------------------
  2995. Purpose: Remove menus that are shared with other menus from
  2996. the given browser menu.
  2997. Returns:
  2998. Cond: --
  2999. */
  3000. HRESULT CBaseBrowser2::RemoveMenusSB(HMENU hmenuShared)
  3001. {
  3002. return S_OK;
  3003. }
  3004. HRESULT CBaseBrowser2::SetStatusTextSB(LPCOLESTR lpszStatusText)
  3005. {
  3006. // Even if we're not toplevel, send this to SendControlMsg
  3007. // so events get notified. (Also simplifies CVOCBrowser.)
  3008. //
  3009. HRESULT hres;
  3010. // If we are asked to put some text into the status bar, first save off what is already in pane 0
  3011. if (lpszStatusText)
  3012. {
  3013. LRESULT lIsSimple = FALSE;
  3014. // If we have a menu down, then we are already in simple mode. So send the
  3015. // text to pane 255 (simple)
  3016. _psbOuter->SendControlMsg(FCW_STATUS, SB_ISSIMPLE, 0, 0L, &lIsSimple);
  3017. if (!_fHaveOldStatusText && !lIsSimple)
  3018. {
  3019. WCHAR wzStatusText[MAX_URL_STRING];
  3020. LRESULT ret;
  3021. // TODO: Put this into a wrapper function because iedisp.cpp does something similar.
  3022. // Great when we convert to UNICODE
  3023. if (SUCCEEDED(_psbOuter->SendControlMsg(FCW_STATUS, SB_GETTEXTLENGTHW, 0, 0, &ret)) &&
  3024. LOWORD(ret) < ARRAYSIZE(wzStatusText))
  3025. {
  3026. // SB_GETTEXTW is not supported by the status bar control in Win95. Hence, the thunk here.
  3027. _psbOuter->SendControlMsg(FCW_STATUS, SB_GETTEXTW, STATUS_PANE_NAVIGATION, (LPARAM)wzStatusText, NULL);
  3028. StrCpyNW(_szwOldStatusText, wzStatusText, ARRAYSIZE(_szwOldStatusText));
  3029. _fHaveOldStatusText = TRUE;
  3030. }
  3031. }
  3032. hres = _psbOuter->SendControlMsg(FCW_STATUS, SB_SETTEXTW, lIsSimple ? 255 | SBT_NOBORDERS : STATUS_PANE_NAVIGATION | SBT_NOTABPARSING, (LPARAM)lpszStatusText, NULL);
  3033. }
  3034. else if (_fHaveOldStatusText)
  3035. {
  3036. VARIANTARG var = {0};
  3037. if (_bbd._pctView && SUCCEEDED(_bbd._pctView->Exec(&CGID_Explorer, SBCMDID_GETPANE, PANE_NAVIGATION, NULL, &var))
  3038. && V_UI4(&var) != PANE_NONE)
  3039. {
  3040. hres = _psbOuter->SendControlMsg(FCW_STATUS, SB_SETTEXTW, V_UI4(&var),(LPARAM)_szwOldStatusText, NULL);
  3041. }
  3042. else
  3043. {
  3044. hres = E_FAIL;
  3045. }
  3046. _fHaveOldStatusText = FALSE;
  3047. }
  3048. else
  3049. {
  3050. // No message, and no old status text, so clear what's there.
  3051. hres = _psbOuter->SendControlMsg(FCW_STATUS, SB_SETTEXTW, STATUS_PANE_NAVIGATION | SBT_NOTABPARSING , (LPARAM)lpszStatusText, NULL);
  3052. }
  3053. return hres;
  3054. }
  3055. HRESULT CBaseBrowser2::EnableModelessSB(BOOL fEnable)
  3056. {
  3057. // We no longer call _CancelNavigation here, which causes some problems
  3058. // when the object calls EnableModeless when we are navigating away
  3059. // (see IE bug 4581). Instead, we either cancel or postpone asynchronous
  3060. // event while _DisableModeless(). (SatoNa)
  3061. //
  3062. // If we're NOT top level, assume virtual EnableModelessSB
  3063. // handled this request and forwarded it to us. (See CVOCBrowser.)
  3064. //
  3065. if (fEnable)
  3066. {
  3067. // Robust against random calls
  3068. //
  3069. // If this EVAL rips, somebody is calling EMSB(TRUE) without a
  3070. // (preceeding) matching EMSB(FALSE). Find and fix!
  3071. //
  3072. if (EVAL(_cRefCannotNavigate > 0))
  3073. {
  3074. _cRefCannotNavigate--;
  3075. }
  3076. // Tell the shell's HTML window to retry pending navigation.
  3077. if (_cRefCannotNavigate == 0 && _phtmlWS)
  3078. {
  3079. _phtmlWS->CanNavigate();
  3080. }
  3081. }
  3082. else
  3083. {
  3084. _cRefCannotNavigate++;
  3085. }
  3086. //
  3087. // If there is any blocked async operation AND we can navigate now,
  3088. // unblock it now.
  3089. //
  3090. _MayUnblockAsyncOperation();
  3091. return S_OK;
  3092. }
  3093. HRESULT CBaseBrowser2::TranslateAcceleratorSB(LPMSG lpmsg, WORD wID)
  3094. {
  3095. return S_FALSE;
  3096. }
  3097. //
  3098. // This function starts the navigation to the navigation to the specified
  3099. // pidl asynchronously. It cancels the pending navigation synchronously
  3100. // if any.
  3101. //
  3102. // NOTE: This function takes ownership of the pidl -- caller does NOT free pidl!!!
  3103. //
  3104. void CBaseBrowser2::_NavigateToPidlAsync(LPITEMIDLIST pidl, DWORD dwSBSP, BOOL fDontCallCancel)
  3105. {
  3106. BOOL fCanSend = FALSE;
  3107. TraceMsg(TF_SHDNAVIGATE, "CBB::_NavigateToPidlAsync called");
  3108. // _StopAsyncOperation();
  3109. if (!fDontCallCancel)
  3110. _CancelPendingNavigation(); // which calls _StopAsyncOperation too
  3111. else
  3112. {
  3113. //
  3114. // I'm removing this assert because _ShowBlankPage calls this funcion
  3115. // with fDontCallCancel==TRUE -- callin _CancelPendingNavigation here
  3116. // causes GPF in CDocHostObject::_CancelPendingNavigation. (SatoNa)
  3117. //
  3118. // ASSERT(_bbd._pidlPending == NULL);
  3119. }
  3120. ASSERT(!_pidlQueued);
  3121. _pidlQueued = pidl;
  3122. _dwSBSPQueued = dwSBSP;
  3123. // Technically a navigate must be async or we have problems such as:
  3124. // 1> object initiating the navigate (mshtml or an object on the page
  3125. // or script) gets destroyed when _bbd._psv is removed and then we return
  3126. // from this call into the just freed object.
  3127. // 2> object initiating the navigate gets called back by an event
  3128. //
  3129. // In order for Netscape OM compatibility, we must ALWAY have a _bbd._psv or
  3130. // _bbd._psvPending, so we go SYNC when we have neither. This avoids problem
  3131. // <1> but not problem <2>. As we find faults, we'll work around them.
  3132. //
  3133. // Check _fAsyncNavigate to avoid navigate when persisting the WebBrowserOC
  3134. // This avoids faults in Word97 and MSDN's new InfoViewer -- neither like
  3135. // being reentered by an object they are in the middle of initializing.
  3136. //
  3137. if (_bbd._psv || _bbd._psvPending || _fAsyncNavigate)
  3138. {
  3139. _PostAsyncOperation(ASYNCOP_GOTO);
  3140. }
  3141. else
  3142. {
  3143. // if we are just starting out, we can do this synchronously and
  3144. // reduce the window where the IHTMLWindow2 for the frame is undefined
  3145. fCanSend = TRUE;
  3146. }
  3147. // Starting a navigate means we are loading someing...
  3148. //
  3149. OnReadyStateChange(NULL, READYSTATE_LOADING);
  3150. //
  3151. // Don't play sound for the first navigation (to avoid multiple
  3152. // sounds to be played for a frame-set creation).
  3153. //
  3154. if ( _bbd._psv
  3155. && IsWindowVisible(_bbd._hwnd)
  3156. && !(_dwSBSPQueued & SBSP_WRITENOHISTORY)
  3157. && !(_dwDocFlags & DOCFLAG_NAVIGATEFROMDOC))
  3158. {
  3159. IEPlaySound(TEXT("Navigating"), FALSE);
  3160. }
  3161. if (fCanSend)
  3162. {
  3163. _SendAsyncOperation(ASYNCOP_GOTO);
  3164. }
  3165. }
  3166. // Now that all navigation paths go through
  3167. // _NavigateToPidlAsync we probably don't need to activate async.
  3168. // Remove this code...
  3169. //
  3170. BOOL CBaseBrowser2::_ActivatePendingViewAsync(void)
  3171. {
  3172. TraceMsg(TF_SHDNAVIGATE, "CBB::_ActivatePendingViewAsync called");
  3173. _PreActivatePendingViewAsync();
  3174. //
  3175. // _bbd._psvPending is for debugging purpose.
  3176. //
  3177. return _PostAsyncOperation(ASYNCOP_ACTIVATEPENDING);
  3178. }
  3179. HRESULT _TryActivateOpenWindow(LPCITEMIDLIST pidl)
  3180. {
  3181. HWND hwnd;
  3182. IWebBrowserApp *pwb;
  3183. HRESULT hr = WinList_FindFolderWindow(pidl, NULL, &hwnd, &pwb);
  3184. if (S_OK == hr)
  3185. {
  3186. CoAllowSetForegroundWindow(pwb, NULL);
  3187. SetForegroundWindow(hwnd);
  3188. ShowWindow(hwnd, SW_SHOWNORMAL);
  3189. pwb->Release();
  3190. }
  3191. return hr;
  3192. }
  3193. HRESULT CBaseBrowser2::BrowseObject(LPCITEMIDLIST pidl, UINT wFlags)
  3194. {
  3195. HRESULT hr;
  3196. BOOL fNewWindow = FALSE;
  3197. if (PIDL_NOTHING == pidl)
  3198. {
  3199. if (!_CanNavigate())
  3200. return HRESULT_FROM_WIN32(ERROR_BUSY);
  3201. _NavigateToPidlAsync((LPITEMIDLIST)PIDL_NOTHING, wFlags);
  3202. return S_OK;
  3203. }
  3204. if (!_CanNavigate())
  3205. return HRESULT_FROM_WIN32(ERROR_BUSY);
  3206. LPITEMIDLIST pidlNew = NULL;
  3207. int iTravel = 0;
  3208. switch (wFlags & (SBSP_RELATIVE | SBSP_ABSOLUTE | SBSP_PARENT | SBSP_NAVIGATEBACK | SBSP_NAVIGATEFORWARD))
  3209. {
  3210. case SBSP_NAVIGATEBACK:
  3211. ASSERT(pidl==NULL || pidl==PIDL_LOCALHISTORY);
  3212. iTravel = TLOG_BACK;
  3213. break;
  3214. case SBSP_NAVIGATEFORWARD:
  3215. ASSERT(pidl==NULL || pidl==PIDL_LOCALHISTORY);
  3216. iTravel = TLOG_FORE;
  3217. break;
  3218. case SBSP_RELATIVE:
  3219. if (ILIsEmpty(pidl) && (wFlags & SBSP_NEWBROWSER))
  3220. fNewWindow = TRUE;
  3221. else if (_bbd._pidlCur)
  3222. pidlNew = ILCombine(_bbd._pidlCur, pidl);
  3223. break;
  3224. case SBSP_PARENT:
  3225. pidlNew = ILCloneParent(_bbd._pidlCur);
  3226. break;
  3227. default:
  3228. ASSERT(FALSE);
  3229. // fall through
  3230. case SBSP_ABSOLUTE:
  3231. pidlNew = ILClone(pidl);
  3232. break;
  3233. }
  3234. if (iTravel)
  3235. {
  3236. ITravelLog *ptl;
  3237. hr = GetTravelLog(&ptl);
  3238. if (SUCCEEDED(hr))
  3239. {
  3240. hr = ptl->Travel(SAFECAST(this, IShellBrowser*), iTravel);
  3241. ptl->Release();
  3242. }
  3243. _pbsOuter->UpdateBackForwardState();
  3244. return hr;
  3245. }
  3246. // if block is needed for multi-window open. if we're called to open a new
  3247. // window, but we're in the middle of navigating, we say we're busy.
  3248. if (wFlags & SBSP_SAMEBROWSER)
  3249. {
  3250. if (wFlags & (SBSP_EXPLOREMODE | SBSP_OPENMODE))
  3251. {
  3252. // fail this if we're already navigating
  3253. if (!_CanNavigate() || (_uActionQueued == ASYNCOP_GOTO))
  3254. {
  3255. return HRESULT_FROM_WIN32(ERROR_BUSY);
  3256. }
  3257. }
  3258. }
  3259. if (pidlNew || fNewWindow)
  3260. {
  3261. if ((wFlags & (SBSP_NEWBROWSER | SBSP_SAMEBROWSER)) == SBSP_NEWBROWSER)
  3262. {
  3263. // SBSP_NEWBROWSER + SBSP_EXPLOREMODE
  3264. // means never reuse windows, always create a new explorer
  3265. if (wFlags & SBSP_EXPLOREMODE)
  3266. {
  3267. _OpenNewFrame(pidlNew, wFlags); // takes ownership of pidl
  3268. }
  3269. else
  3270. {
  3271. hr = _TryActivateOpenWindow(pidlNew);
  3272. if ((S_OK == hr) ||
  3273. (E_PENDING == hr)) // it will come up eventually
  3274. {
  3275. hr = S_OK;
  3276. ILFree(pidlNew);
  3277. }
  3278. else
  3279. _OpenNewFrame(pidlNew, wFlags); // takes ownership of pidl
  3280. }
  3281. }
  3282. else
  3283. {
  3284. // NOTE: we assume SBSP_SAMEBROWSER if SBSP_NEWBROWSER is not set
  3285. _NavigateToPidlAsync(pidlNew, wFlags /* grfSBSP */); // takes ownership of pidl
  3286. }
  3287. hr = S_OK;
  3288. }
  3289. else
  3290. {
  3291. hr = E_OUTOFMEMORY;
  3292. }
  3293. return hr;
  3294. }
  3295. HRESULT CBaseBrowser2::GetControlWindow(UINT id, HWND * lphwnd)
  3296. {
  3297. return E_FAIL;
  3298. }
  3299. HRESULT CBaseBrowser2::SendControlMsg(UINT id, UINT uMsg, WPARAM wParam,
  3300. LPARAM lParam, LRESULT *pret)
  3301. {
  3302. HWND hwndControl = NULL;
  3303. if (pret)
  3304. {
  3305. *pret = 0;
  3306. }
  3307. // If this is statusbar and set text then signal event change.
  3308. if ((id == FCW_STATUS) && (uMsg == SB_SETTEXT || uMsg == SB_SETTEXTW) && // trying to set status text
  3309. (!(wParam & SBT_OWNERDRAW))) // we don't own the window -- this can't work
  3310. {
  3311. // When browser or java perf timing mode is enabled, use "Done" or "Applet Started"
  3312. // in the status bar to get load time.
  3313. if(g_dwStopWatchMode && (g_dwStopWatchMode & (SPMODE_BROWSER | SPMODE_JAVA)))
  3314. {
  3315. StopWatch_MarkJavaStop((LPSTR)lParam, _bbd._hwnd, (uMsg == SB_SETTEXTW));
  3316. }
  3317. if (uMsg == SB_SETTEXTW)
  3318. {
  3319. FireEvent_DoInvokeStringW(_bbd._pautoEDS, DISPID_STATUSTEXTCHANGE, (LPWSTR)lParam);
  3320. }
  3321. else
  3322. {
  3323. FireEvent_DoInvokeString(_bbd._pautoEDS, DISPID_STATUSTEXTCHANGE, (LPSTR)lParam);
  3324. }
  3325. }
  3326. HRESULT hres = _psbOuter->GetControlWindow(id, &hwndControl);
  3327. if (SUCCEEDED(hres))
  3328. {
  3329. LRESULT ret = SendMessage(hwndControl, uMsg, wParam, lParam);
  3330. if (pret)
  3331. {
  3332. *pret = ret;
  3333. }
  3334. }
  3335. return hres;
  3336. }
  3337. HRESULT CBaseBrowser2::QueryActiveShellView(struct IShellView ** ppshv)
  3338. {
  3339. IShellView * psvRet = _bbd._psv;
  3340. if ( _fCreateViewWindowPending )
  3341. {
  3342. ASSERT( _bbd._psvPending );
  3343. psvRet = _bbd._psvPending;
  3344. }
  3345. //
  3346. // We have both psv and hwndView after the completion of view creation.
  3347. //
  3348. *ppshv = psvRet;
  3349. if (psvRet)
  3350. {
  3351. psvRet->AddRef();
  3352. return NOERROR;
  3353. }
  3354. return E_FAIL;
  3355. }
  3356. HRESULT CBaseBrowser2::OnViewWindowActive(struct IShellView * psv)
  3357. {
  3358. AssertMsg((!_bbd._psv || IsSameObject(_bbd._psv, psv)),
  3359. TEXT("CBB::OnViewWindowActive _bbd._psv(%x)!=psv(%x)"),
  3360. psv, _bbd._psv);
  3361. _pbsOuter->_OnFocusChange(ITB_VIEW);
  3362. return S_OK;
  3363. }
  3364. HRESULT CBaseBrowser2::SetToolbarItems(LPTBBUTTON pViewButtons, UINT nButtons, UINT uFlags)
  3365. {
  3366. return NOERROR;
  3367. }
  3368. //
  3369. // Notes: pidlNew will be freed
  3370. //
  3371. HRESULT CBaseBrowser2::_OpenNewFrame(LPITEMIDLIST pidlNew, UINT wFlags)
  3372. {
  3373. UINT uFlags = COF_CREATENEWWINDOW;
  3374. if (wFlags & SBSP_EXPLOREMODE)
  3375. uFlags |= COF_EXPLORE;
  3376. else
  3377. {
  3378. // maintain the same class if possible
  3379. if (IsNamedWindow(_bbd._hwnd, TEXT("IEFrame")))
  3380. uFlags |= COF_IEXPLORE;
  3381. }
  3382. IBrowserService *pbs;
  3383. ITravelLog *ptlClone = NULL;
  3384. DWORD bid = BID_TOPFRAMEBROWSER;
  3385. if (!(wFlags & SBSP_NOTRANSFERHIST))
  3386. {
  3387. if (SUCCEEDED(_pspOuter->QueryService(SID_STopFrameBrowser, IID_PPV_ARG(IBrowserService, &pbs))))
  3388. {
  3389. ITravelLog *ptl;
  3390. if (SUCCEEDED(pbs->GetTravelLog(&ptl)))
  3391. {
  3392. if (SUCCEEDED(ptl->Clone(&ptlClone)))
  3393. {
  3394. ptlClone->UpdateEntry(pbs, FALSE);
  3395. bid = pbs->GetBrowserIndex();
  3396. }
  3397. ptl->Release();
  3398. }
  3399. pbs->Release();
  3400. }
  3401. }
  3402. INotifyAppStart * pnasTop;
  3403. HRESULT hr = _pspOuter->QueryService(SID_STopLevelBrowser, IID_PPV_ARG(INotifyAppStart, &pnasTop));
  3404. if (SUCCEEDED(hr))
  3405. {
  3406. pnasTop->AppStarting();
  3407. pnasTop->Release();
  3408. }
  3409. hr = SHOpenNewFrame(pidlNew, ptlClone, bid, uFlags);
  3410. if (ptlClone)
  3411. ptlClone->Release();
  3412. return hr;
  3413. }
  3414. //
  3415. // This is a helper member of CBaseBroaser class (non-virtual), which
  3416. // returns the effective client area. We get this rectangle by subtracting
  3417. // the status bar area from the real client area.
  3418. //
  3419. HRESULT CBaseBrowser2::_GetEffectiveClientArea(LPRECT lprectBorder, HMONITOR hmon)
  3420. {
  3421. // (derived class overrides w/ GetEffectiveClientRect for FCIDM_STATUS etc.)
  3422. //
  3423. // This code should only be hit in the WebBrowserOC case, but I don't
  3424. // have a convenient assert for that... [mikesh]
  3425. //
  3426. ASSERT(hmon == NULL);
  3427. GetClientRect(_bbd._hwnd, lprectBorder);
  3428. return NOERROR;
  3429. }
  3430. HRESULT CBaseBrowser2::RequestBorderSpace(LPCBORDERWIDTHS pborderwidths)
  3431. {
  3432. TraceMsg(TF_SHDUIACTIVATE, "UIW::ReqestBorderSpace pborderwidths=%x,%x,%x,%x",
  3433. pborderwidths->left, pborderwidths->top, pborderwidths->right, pborderwidths->bottom);
  3434. return S_OK;
  3435. }
  3436. //
  3437. // This is an implementation of IOleInPlaceUIWindow::GetBorder.
  3438. //
  3439. // This function returns the bounding rectangle for the active object.
  3440. // It gets the effective client area, then subtract border area taken by
  3441. // all "frame" toolbars.
  3442. //
  3443. HRESULT CBaseBrowser2::GetBorder(LPRECT lprectBorder)
  3444. {
  3445. _pbsOuter->_GetViewBorderRect(lprectBorder);
  3446. return S_OK;
  3447. }
  3448. //
  3449. // NOTES: We used to handle the border space negotiation in CShellBrowser
  3450. // and block it for OC (in Beta-1 of IE4), but I've changed it so that
  3451. // CBaseBrowser2 always handles it. It simplifies our implementation and
  3452. // also allows a DocObject to put toolbars within the frameset, which is
  3453. // requested by the Excel team. (SatoNa)
  3454. //
  3455. HRESULT CBaseBrowser2::SetBorderSpace(LPCBORDERWIDTHS pborderwidths)
  3456. {
  3457. if (pborderwidths)
  3458. {
  3459. TraceMsg(TF_SHDUIACTIVATE, "UIW::SetBorderSpace pborderwidths=%x,%x,%x,%x",
  3460. pborderwidths->left, pborderwidths->top, pborderwidths->right, pborderwidths->bottom);
  3461. _rcBorderDoc = *pborderwidths;
  3462. }
  3463. else
  3464. {
  3465. TraceMsg(TF_SHDUIACTIVATE, "UIW::SetBorderSpace pborderwidths=NULL");
  3466. SetRect(&_rcBorderDoc, 0, 0, 0, 0);
  3467. }
  3468. _pbsOuter->_UpdateViewRectSize();
  3469. return S_OK;
  3470. }
  3471. HRESULT CBaseBrowser2::SetActiveObject(IOleInPlaceActiveObject *pActiveObject, LPCOLESTR pszObjName)
  3472. {
  3473. TraceMsg(TF_SHDUIACTIVATE, "UIW::SetActiveObject called %x", pActiveObject);
  3474. ATOMICRELEASE(_pact);
  3475. if (pActiveObject)
  3476. {
  3477. _pact = pActiveObject;
  3478. _pact->AddRef();
  3479. }
  3480. return S_OK;
  3481. }
  3482. /***********************************************************************\
  3483. FUNCTION: _AddFolderOptionsSheets
  3484. DESCRIPTION:
  3485. Add the sheets for the "Folder Options" dialog. These sheets
  3486. come from the IShelLView object.
  3487. \***********************************************************************/
  3488. HRESULT CBaseBrowser2::_AddFolderOptionsSheets(DWORD dwReserved, LPFNADDPROPSHEETPAGE pfnAddPropSheetPage, LPPROPSHEETHEADER ppsh)
  3489. {
  3490. // Add the normal Folder Option sheets.
  3491. IShellPropSheetExt * ppsx;
  3492. HRESULT hr = _pbsOuter->CreateBrowserPropSheetExt(IID_PPV_ARG(IShellPropSheetExt, &ppsx));
  3493. if (SUCCEEDED(hr))
  3494. {
  3495. hr = ppsx->AddPages(AddPropSheetPage, (LPARAM)ppsh);
  3496. ppsx->Release();
  3497. }
  3498. // Let the view add additional pages. The exception will be FTP Folders because it exists to add
  3499. // internet pages and we don't want them here. However, if the above failed, then
  3500. // we also want to fall back to this. One of the cases this fixes if if the
  3501. // browser fell back to legacy FTP support (web browser), then the above call will
  3502. // fail on browser only, and we want to fall thru here to add the internet options. Which
  3503. // is appropriate for the fallback legacy FTP case because the menu will only have "Internet Options"
  3504. // on it.
  3505. if (FAILED(hr) || !IsBrowserFrameOptionsSet(_bbd._psf, BFO_BOTH_OPTIONS))
  3506. {
  3507. EVAL(SUCCEEDED(hr = _bbd._psv->AddPropertySheetPages(dwReserved, pfnAddPropSheetPage, (LPARAM)ppsh)));
  3508. }
  3509. return hr;
  3510. }
  3511. /***********************************************************************\
  3512. FUNCTION: _AddInternetOptionsSheets
  3513. DESCRIPTION:
  3514. Add the sheets for the "Internet Options" dialog. These sheets
  3515. come from the browser.
  3516. \***********************************************************************/
  3517. HRESULT CBaseBrowser2::_AddInternetOptionsSheets(DWORD dwReserved, LPFNADDPROPSHEETPAGE pfnAddPropSheetPage, LPPROPSHEETHEADER ppsh)
  3518. {
  3519. HRESULT hr;
  3520. // Add the normal Internet Control Panel sheets. (This won't work when viewing FTP)
  3521. if (_bbd._psvPending)
  3522. hr = _bbd._psvPending->AddPropertySheetPages(dwReserved, pfnAddPropSheetPage, (LPARAM)ppsh);
  3523. else
  3524. hr = _bbd._psv->AddPropertySheetPages(dwReserved, pfnAddPropSheetPage, (LPARAM)ppsh);
  3525. return hr;
  3526. }
  3527. /***********************************************************************\
  3528. FUNCTION: _DoOptions
  3529. DESCRIPTION:
  3530. The user selected either "Folder Options" or "Internet Options" from
  3531. the View or Tools menu (or where ever it lives this week). The logic
  3532. in this function is a little strange because sometimes the caller doesn't
  3533. tell us which we need to display in the pvar. If not, we need to calculate
  3534. what to use.
  3535. 1. If it's a URL pidl (HTTP, GOPHER, etc) then we assume it's the
  3536. "Internet Options" dialog. We then use psv->AddPropertySheetPages()
  3537. to create the "Internet Options" property sheets.
  3538. 2. If it's in the shell (or FTP because it needs folder options), then
  3539. we assume it's "Folder Options" the user selected. In that case,
  3540. we get the property sheets using _pbsOuter->CreateBrowserPropSheetExt().
  3541. Now it gets weird. The PMs want FTP to have both "Internet Options" and
  3542. "Folder Options". If the pvar param is NULL, assume it's "Folder Options".
  3543. If it was "Internet Options" in the internet case, then I will pass an
  3544. pvar forcing Internet Options.
  3545. NOTE: SBO_NOBROWSERPAGES means "Folder Options". I'm guessing browser refers
  3546. to the original explorer browser.
  3547. \***********************************************************************/
  3548. HDPA CBaseBrowser2::s_hdpaOptionsHwnd = NULL;
  3549. void CBaseBrowser2::_DoOptions(VARIANT* pvar)
  3550. {
  3551. // Step 1. Determine what sheets to use.
  3552. DWORD dwFlags = SBO_DEFAULT;
  3553. TCHAR szCaption[MAX_PATH];
  3554. if (!_bbd._psv)
  3555. return;
  3556. // Did the caller explicitly tell us which to use?
  3557. if (pvar && pvar->vt == VT_I4)
  3558. dwFlags = pvar->lVal;
  3559. else if (_bbd._pidlCur)
  3560. {
  3561. // don't show the Folder Option pages if
  3562. // 1. we're browsing the internet (excluding FTP), or
  3563. // 2. if we're browsing a local file (not a folder), like a local .htm file.
  3564. if (IsBrowserFrameOptionsSet(_bbd._psf, BFO_RENAME_FOLDER_OPTIONS_TOINTERNET))
  3565. {
  3566. // SBO_NOBROWSERPAGES means don't add the "Folder Options" pages.
  3567. dwFlags = SBO_NOBROWSERPAGES;
  3568. }
  3569. }
  3570. PROPSHEETHEADER psh;
  3571. HPROPSHEETPAGE rPages[MAX_PAGES];
  3572. psh.dwSize = SIZEOF(psh);
  3573. psh.dwFlags = PSH_DEFAULT | PSH_USECALLBACK;
  3574. psh.hInstance = MLGetHinst();
  3575. psh.hwndParent = _bbd._hwnd;
  3576. psh.pszCaption = szCaption;
  3577. psh.nPages = 0;
  3578. psh.nStartPage = 0;
  3579. psh.phpage = rPages;
  3580. psh.pfnCallback = _OptionsPropSheetCallback;
  3581. // Step 2. Now add "Internet Options" or "Folder Options" sheets.
  3582. if (dwFlags == SBO_NOBROWSERPAGES)
  3583. {
  3584. // They don't want folder pages. (The used to refer to it as browser)
  3585. EVAL(SUCCEEDED(_AddInternetOptionsSheets(0, AddPropSheetPage, &psh)));
  3586. MLLoadString(IDS_INTERNETOPTIONS, szCaption, ARRAYSIZE(szCaption));
  3587. }
  3588. else
  3589. {
  3590. EVAL(SUCCEEDED(_AddFolderOptionsSheets(0, AddPropSheetPage, &psh)));
  3591. MLLoadString(IDS_FOLDEROPTIONS, szCaption, ARRAYSIZE(szCaption));
  3592. }
  3593. ULONG_PTR uCookie = 0;
  3594. SHActivateContext(&uCookie);
  3595. if (psh.nPages == 0)
  3596. {
  3597. SHRestrictedMessageBox(_bbd._hwnd);
  3598. }
  3599. else
  3600. {
  3601. // Step 3. Display the dialog
  3602. _bbd._psv->EnableModelessSV(FALSE);
  3603. INT_PTR iPsResult = PropertySheet(&psh);
  3604. _SyncDPA();
  3605. _bbd._psv->EnableModelessSV(TRUE);
  3606. if (ID_PSREBOOTSYSTEM == iPsResult)
  3607. {
  3608. // The "offline folders" prop page will request a reboot if the user
  3609. // has enabled or disabled client-side-caching.
  3610. RestartDialog(_bbd._hwnd, NULL, EWX_REBOOT);
  3611. }
  3612. }
  3613. if (uCookie)
  3614. {
  3615. SHDeactivateContext(uCookie);
  3616. }
  3617. }
  3618. // we're here because our prop sheet just closed
  3619. // we need to purge it from the hwnd list
  3620. // check all the hwnds because 1) there's probably
  3621. // only one anyway, 2) paranoia.
  3622. void CBaseBrowser2::_SyncDPA()
  3623. {
  3624. ENTERCRITICAL;
  3625. if (s_hdpaOptionsHwnd != NULL)
  3626. {
  3627. int i, cPtr = DPA_GetPtrCount(s_hdpaOptionsHwnd);
  3628. ASSERT(cPtr >= 0);
  3629. // remove handles for windows which aren't there anymore
  3630. for (i = cPtr - 1; i >= 0; i--)
  3631. {
  3632. HWND hwnd = (HWND)DPA_GetPtr(s_hdpaOptionsHwnd, i);
  3633. if (!IsWindow(hwnd))
  3634. {
  3635. DPA_DeletePtr(s_hdpaOptionsHwnd, i);
  3636. cPtr--;
  3637. }
  3638. }
  3639. // if there aren't any windows left then clean up the hdpa
  3640. if (cPtr == 0)
  3641. {
  3642. DPA_Destroy(s_hdpaOptionsHwnd);
  3643. s_hdpaOptionsHwnd = NULL;
  3644. }
  3645. }
  3646. LEAVECRITICAL;
  3647. }
  3648. int CALLBACK
  3649. CBaseBrowser2::_OptionsPropSheetCallback(HWND hwndDlg, UINT uMsg, LPARAM lParam)
  3650. {
  3651. switch (uMsg)
  3652. {
  3653. case PSCB_INITIALIZED:
  3654. {
  3655. ENTERCRITICAL;
  3656. if (s_hdpaOptionsHwnd == NULL)
  3657. {
  3658. // low mem -> Create failure -> don't track hwnd
  3659. s_hdpaOptionsHwnd = DPA_Create(1);
  3660. }
  3661. if (s_hdpaOptionsHwnd != NULL)
  3662. {
  3663. // low mem -> AppendPtr array expansion failure -> don't track hwnd
  3664. DPA_AppendPtr(s_hdpaOptionsHwnd, hwndDlg);
  3665. }
  3666. LEAVECRITICAL;
  3667. }
  3668. break;
  3669. }
  3670. return 0;
  3671. }
  3672. HRESULT CBaseBrowser2::QueryStatus(const GUID *pguidCmdGroup, ULONG cCmds,
  3673. OLECMD rgCmds[], OLECMDTEXT *pcmdtext)
  3674. {
  3675. if (rgCmds == NULL)
  3676. return E_INVALIDARG;
  3677. if (pguidCmdGroup == NULL)
  3678. {
  3679. for (ULONG i = 0 ; i < cCmds; i++)
  3680. {
  3681. rgCmds[i].cmdf = 0;
  3682. switch (rgCmds[i].cmdID)
  3683. {
  3684. case OLECMDID_SETDOWNLOADSTATE:
  3685. case OLECMDID_UPDATECOMMANDS:
  3686. rgCmds[i].cmdf = OLECMDF_ENABLED;
  3687. break;
  3688. case OLECMDID_STOP:
  3689. case OLECMDID_STOPDOWNLOAD:
  3690. if (_bbd._psvPending) // pending views are stoppable
  3691. {
  3692. rgCmds[i].cmdf = OLECMDF_ENABLED;
  3693. }
  3694. else if (_bbd._pctView) // current views may support stop also
  3695. {
  3696. _bbd._pctView->QueryStatus(NULL, 1, &rgCmds[i], pcmdtext);
  3697. }
  3698. break;
  3699. default:
  3700. // set to zero above
  3701. if (_bbd._pctView)
  3702. {
  3703. // Recursion check. Avoid looping for those command IDs where Trident bounces
  3704. // back up to us.
  3705. //
  3706. if (_fInQueryStatus)
  3707. break;
  3708. _fInQueryStatus = TRUE;
  3709. _bbd._pctView->QueryStatus(NULL, 1, &rgCmds[i], pcmdtext);
  3710. _fInQueryStatus = FALSE;
  3711. }
  3712. break;
  3713. }
  3714. }
  3715. }
  3716. else if (IsEqualGUID(CGID_Explorer, *pguidCmdGroup))
  3717. {
  3718. for (ULONG i=0 ; i < cCmds ; i++)
  3719. {
  3720. switch (rgCmds[i].cmdID)
  3721. {
  3722. case SBCMDID_ADDTOFAVORITES:
  3723. case SBCMDID_CREATESHORTCUT:
  3724. rgCmds[i].cmdf = OLECMDF_ENABLED; // support these unconditionally
  3725. break;
  3726. case SBCMDID_CANCELNAVIGATION:
  3727. rgCmds[i].cmdf = _bbd._psvPending ? OLECMDF_ENABLED : 0;
  3728. break;
  3729. case SBCMDID_OPTIONS:
  3730. rgCmds[i].cmdf = OLECMDF_ENABLED;
  3731. break;
  3732. default:
  3733. rgCmds[i].cmdf = 0;
  3734. break;
  3735. }
  3736. }
  3737. }
  3738. else if (IsEqualGUID(CGID_ShellDocView, *pguidCmdGroup))
  3739. {
  3740. for (ULONG i=0 ; i < cCmds ; i++)
  3741. {
  3742. ITravelLog *ptl;
  3743. switch (rgCmds[i].cmdID)
  3744. {
  3745. case SHDVID_CANGOBACK:
  3746. rgCmds[i].cmdf = FALSE; // Assume False
  3747. if (SUCCEEDED(GetTravelLog(&ptl)))
  3748. {
  3749. ASSERT(ptl);
  3750. if (S_OK == ptl->GetTravelEntry(SAFECAST(this, IShellBrowser *), TLOG_BACK, NULL))
  3751. rgCmds[i].cmdf = TRUE;
  3752. ptl->Release();
  3753. }
  3754. break;
  3755. case SHDVID_CANGOFORWARD:
  3756. rgCmds[i].cmdf = FALSE; // Assume False
  3757. if (SUCCEEDED(GetTravelLog(&ptl)))
  3758. {
  3759. ASSERT(ptl);
  3760. if (S_OK == ptl->GetTravelEntry(SAFECAST(this, IShellBrowser *), TLOG_FORE, NULL))
  3761. rgCmds[i].cmdf = TRUE;
  3762. ptl->Release();
  3763. }
  3764. break;
  3765. case SHDVID_PRINTFRAME:
  3766. case SHDVID_MIMECSETMENUOPEN:
  3767. case SHDVID_FONTMENUOPEN:
  3768. if (_bbd._pctView)
  3769. _bbd._pctView->QueryStatus(pguidCmdGroup, 1, &rgCmds[i], pcmdtext);
  3770. break;
  3771. default:
  3772. rgCmds[i].cmdf = 0;
  3773. break;
  3774. }
  3775. }
  3776. }
  3777. else
  3778. {
  3779. return OLECMDERR_E_UNKNOWNGROUP;
  3780. }
  3781. return S_OK;
  3782. }
  3783. HRESULT CBaseBrowser2::_ShowBlankPage(LPCTSTR pszAboutUrl, LPCITEMIDLIST pidlIntended)
  3784. {
  3785. // Never execute this twice.
  3786. if (_fNavigatedToBlank)
  3787. {
  3788. TraceMsg(TF_WARNING, "Re-entered CBaseBrowser2::_ShowBlankPage");
  3789. return E_FAIL;
  3790. }
  3791. _fNavigatedToBlank = TRUE;
  3792. BSTR bstrURL;
  3793. TCHAR szPendingURL[MAX_URL_STRING + 1];
  3794. TCHAR *pszOldUrl = NULL;
  3795. szPendingURL[0] = TEXT('#');
  3796. HRESULT hres;
  3797. if (pidlIntended)
  3798. {
  3799. hres = ::IEGetNameAndFlags(pidlIntended, SHGDN_FORPARSING, szPendingURL + 1, SIZECHARS(szPendingURL)-1, NULL);
  3800. if (S_OK == hres)
  3801. pszOldUrl = szPendingURL;
  3802. }
  3803. hres = CreateBlankURL(&bstrURL, pszAboutUrl, pszOldUrl);
  3804. if (SUCCEEDED(hres))
  3805. {
  3806. LPITEMIDLIST pidlTemp;
  3807. hres = IECreateFromPathW(bstrURL, &pidlTemp);
  3808. if (SUCCEEDED(hres))
  3809. {
  3810. //
  3811. // Note that we pass TRUE as fDontCallCancel to asynchronously
  3812. // cancel the current view. Otherwise, we hit GPF in CDocHostObject::
  3813. // _CancelPendingNavigation.
  3814. //
  3815. _NavigateToPidlAsync(pidlTemp, 0, TRUE); // takes ownership of pidl
  3816. }
  3817. SysFreeString(bstrURL);
  3818. }
  3819. return hres;
  3820. }
  3821. int CALLBACK _PunkRelease(void * p, void * pData)
  3822. {
  3823. IUnknown* punk = (IUnknown*)p;
  3824. punk->Release();
  3825. return 1;
  3826. }
  3827. void CBaseBrowser2::_DLMDestroy(void)
  3828. {
  3829. if (_hdpaDLM)
  3830. {
  3831. DPA_DestroyCallback(_hdpaDLM, _PunkRelease, NULL);
  3832. _hdpaDLM = NULL;
  3833. }
  3834. }
  3835. HRESULT CBaseBrowser2::InitializeDownloadManager()
  3836. {
  3837. _hdpaDLM = DPA_Create(4);
  3838. return S_OK;
  3839. }
  3840. //
  3841. // DLM = DownLoad Manager
  3842. //
  3843. void CBaseBrowser2::_DLMUpdate(MSOCMD* prgCmd)
  3844. {
  3845. ASSERT(prgCmd->cmdID == OLECMDID_STOPDOWNLOAD);
  3846. for (int i = DPA_GetPtrCount(_hdpaDLM) - 1; i >= 0; i--)
  3847. {
  3848. IOleCommandTarget* pcmdt = (IOleCommandTarget*)DPA_GetPtr(_hdpaDLM, i);
  3849. prgCmd->cmdf = 0;
  3850. pcmdt->QueryStatus(NULL, 1, prgCmd, NULL);
  3851. if (prgCmd->cmdf & MSOCMDF_ENABLED)
  3852. {
  3853. // We found one downloading guy, skip others.
  3854. break;
  3855. }
  3856. else
  3857. {
  3858. // This guy is no longer busy, remove it from the list,
  3859. // and continue.
  3860. DPA_DeletePtr(_hdpaDLM, i);
  3861. pcmdt->Release();
  3862. }
  3863. }
  3864. }
  3865. void CBaseBrowser2::_DLMRegister(IUnknown* punk)
  3866. {
  3867. // Check if it's already registered.
  3868. for (int i = 0; i < DPA_GetPtrCount(_hdpaDLM); i++)
  3869. {
  3870. IOleCommandTarget* pcmdt = (IOleCommandTarget*)DPA_GetPtr(_hdpaDLM, i);
  3871. if (IsSameObject(pcmdt, punk))
  3872. {
  3873. // Already registered, don't register.
  3874. return;
  3875. }
  3876. }
  3877. IOleCommandTarget* pcmdt;
  3878. HRESULT hres = punk->QueryInterface(IID_PPV_ARG(IOleCommandTarget, &pcmdt));
  3879. if (SUCCEEDED(hres))
  3880. {
  3881. if (DPA_AppendPtr(_hdpaDLM, pcmdt) == -1)
  3882. {
  3883. pcmdt->Release();
  3884. }
  3885. }
  3886. }
  3887. //
  3888. // This function updates the _fDescendentNavigate flag.
  3889. //
  3890. // ALGORITHM:
  3891. // If pvaragIn->lVal has some non-zero value, we set _fDescendentNavigate.
  3892. // Otherwise, we ask the current view to see if it has something to stop.
  3893. //
  3894. HRESULT CBaseBrowser2::_setDescendentNavigate(VARIANTARG *pvarargIn)
  3895. {
  3896. ASSERT(!pvarargIn || pvarargIn->vt == VT_I4 || pvarargIn->vt == VT_BOOL || pvarargIn->vt == VT_UNKNOWN);
  3897. if (!pvarargIn || !pvarargIn->lVal)
  3898. {
  3899. MSOCMD rgCmd;
  3900. rgCmd.cmdID = OLECMDID_STOPDOWNLOAD;
  3901. rgCmd.cmdf = 0;
  3902. if (_bbd._pctView)
  3903. _bbd._pctView->QueryStatus(NULL, 1, &rgCmd, NULL);
  3904. //
  3905. // If and only if the view says "I'm not navigating any more",
  3906. // we'll ask the same question to each registered objects.
  3907. //
  3908. if (_hdpaDLM && !(rgCmd.cmdf & MSOCMDF_ENABLED))
  3909. {
  3910. _DLMUpdate(&rgCmd);
  3911. }
  3912. _fDescendentNavigate = (rgCmd.cmdf & MSOCMDF_ENABLED) ? TRUE:FALSE;
  3913. }
  3914. else
  3915. {
  3916. if (_hdpaDLM && pvarargIn->vt == VT_UNKNOWN)
  3917. {
  3918. ASSERT(pvarargIn->punkVal);
  3919. _DLMRegister(pvarargIn->punkVal);
  3920. }
  3921. _fDescendentNavigate = TRUE;
  3922. }
  3923. return S_OK;
  3924. }
  3925. void CBaseBrowser2::_CreateShortcutOnDesktop(IUnknown *pUnk, BOOL fUI)
  3926. {
  3927. ISHCUT_PARAMS ShCutParams = {0};
  3928. IWebBrowser *pwb = NULL;
  3929. IDispatch *pdisp = NULL;
  3930. IHTMLDocument2 *pDoc = NULL;
  3931. LPITEMIDLIST pidlCur = NULL;
  3932. BSTR bstrTitle = NULL;
  3933. BSTR bstrURL = NULL;
  3934. if (!fUI || (MLShellMessageBox(_bbd._hwnd,
  3935. MAKEINTRESOURCE(IDS_CREATE_SHORTCUT_MSG),
  3936. MAKEINTRESOURCE(IDS_TITLE),
  3937. MB_OKCANCEL) == IDOK))
  3938. {
  3939. TCHAR szPath[MAX_PATH];
  3940. if (SHGetSpecialFolderPath(NULL, szPath, CSIDL_DESKTOPDIRECTORY, TRUE))
  3941. {
  3942. TCHAR szName[MAX_URL_STRING];
  3943. HRESULT hr;
  3944. if (pUnk)
  3945. {
  3946. hr = IUnknown_QueryService(pUnk, SID_SHlinkFrame, IID_PPV_ARG(IWebBrowser, &pwb));
  3947. if (hr)
  3948. goto Cleanup;
  3949. hr = pUnk->QueryInterface(IID_PPV_ARG(IHTMLDocument2, &pDoc));
  3950. if (hr)
  3951. goto Cleanup;
  3952. hr = pDoc->get_URL(&bstrURL);
  3953. if (hr)
  3954. goto Cleanup;
  3955. hr = pDoc->get_title(&bstrTitle);
  3956. if (hr)
  3957. goto Cleanup;
  3958. if (SysStringLen(bstrTitle) == 0)
  3959. {
  3960. StrCpyNW(szName, bstrURL, ARRAYSIZE(szName));
  3961. ShCutParams.pszTitle = PathFindFileName(szName);
  3962. }
  3963. else
  3964. {
  3965. StrCpyNW(szName, bstrTitle, ARRAYSIZE(szName));
  3966. ShCutParams.pszTitle = szName;
  3967. }
  3968. pidlCur = PidlFromUrl(bstrURL);
  3969. if (!pidlCur)
  3970. goto Cleanup;
  3971. ShCutParams.pidlTarget = pidlCur;
  3972. }
  3973. else
  3974. {
  3975. hr = QueryService(SID_SHlinkFrame, IID_PPV_ARG(IWebBrowser, &pwb));
  3976. if (hr)
  3977. goto Cleanup;
  3978. hr = pwb->get_Document(&pdisp);
  3979. if (hr)
  3980. goto Cleanup;
  3981. hr = pdisp->QueryInterface(IID_PPV_ARG(IHTMLDocument2, &pDoc));
  3982. if (hr)
  3983. goto Cleanup;
  3984. ShCutParams.pidlTarget = _bbd._pidlCur;
  3985. if(_bbd._pszTitleCur)
  3986. {
  3987. StrCpyNW(szName, _bbd._pszTitleCur, ARRAYSIZE(szName));
  3988. ShCutParams.pszTitle = szName;
  3989. }
  3990. else
  3991. {
  3992. ::IEGetNameAndFlags(_bbd._pidlCur, SHGDN_INFOLDER, szName, SIZECHARS(szName), NULL);
  3993. ShCutParams.pszTitle = PathFindFileName(szName);
  3994. }
  3995. }
  3996. ShCutParams.pszDir = szPath;
  3997. ShCutParams.pszOut = NULL;
  3998. ShCutParams.bUpdateProperties = FALSE;
  3999. ShCutParams.bUniqueName = TRUE;
  4000. ShCutParams.bUpdateIcon = TRUE;
  4001. hr = pwb->QueryInterface(IID_PPV_ARG(IOleCommandTarget, &ShCutParams.pCommand));
  4002. ASSERT((S_OK == hr) && (BOOLIFY(ShCutParams.pCommand)));
  4003. if (hr)
  4004. goto Cleanup;
  4005. ShCutParams.pDoc = pDoc;
  4006. ShCutParams.pDoc->AddRef();
  4007. hr = CreateShortcutInDirEx(&ShCutParams);
  4008. AssertMsg(SUCCEEDED(hr), TEXT("CDOH::_CSOD CreateShortcutInDir failed %x"), hr);
  4009. if (hr)
  4010. goto Cleanup;
  4011. }
  4012. else
  4013. {
  4014. TraceMsg(DM_ERROR, "CSB::_CSOD SHGetSFP(DESKTOP) failed");
  4015. }
  4016. }
  4017. Cleanup:
  4018. SysFreeString(bstrTitle);
  4019. SysFreeString(bstrURL);
  4020. ILFree(pidlCur);
  4021. SAFERELEASE(ShCutParams.pDoc);
  4022. SAFERELEASE(ShCutParams.pCommand);
  4023. SAFERELEASE(pwb);
  4024. SAFERELEASE(pdisp);
  4025. SAFERELEASE(pDoc);
  4026. }
  4027. void CBaseBrowser2::_AddToFavorites(LPCITEMIDLIST pidl, LPCTSTR pszTitle, BOOL fDisplayUI)
  4028. {
  4029. HRESULT hr;
  4030. IWebBrowser *pwb = NULL;
  4031. IOleCommandTarget *pcmdt = NULL;
  4032. if (SHIsRestricted2W(_bbd._hwnd, REST_NoFavorites, NULL, 0))
  4033. return;
  4034. hr = QueryService(SID_SHlinkFrame, IID_PPV_ARG(IWebBrowser, &pwb));
  4035. if (S_OK == hr)
  4036. {
  4037. hr = pwb->QueryInterface(IID_PPV_ARG(IOleCommandTarget, &pcmdt));
  4038. ASSERT((S_OK == hr) && (BOOLIFY(pcmdt)));
  4039. pwb->Release();
  4040. }
  4041. //there's a small window where _pidlCur can be freed while AddToFavorites is coming up,
  4042. // so use a local copy instead
  4043. LPITEMIDLIST pidlCur = NULL;
  4044. if (!pidl)
  4045. pidlCur = ILClone(_bbd._pidlCur);
  4046. if (pidl || pidlCur)
  4047. AddToFavorites(_bbd._hwnd, pidl ? pidl : pidlCur, pszTitle, fDisplayUI, pcmdt, NULL);
  4048. ILFree(pidlCur);
  4049. SAFERELEASE(pcmdt);
  4050. }
  4051. HRESULT CBaseBrowser2::_OnCoCreateDocument(VARIANTARG *pvarargOut)
  4052. {
  4053. HRESULT hres;
  4054. //
  4055. // Cache the class factory object and lock it (leave it loaded)
  4056. //
  4057. if (_pcfHTML == NULL)
  4058. {
  4059. TraceMsg(DM_COCREATEHTML, "CBB::_OnCoCreateDoc called first time (this=%x)", this);
  4060. hres = CoGetClassObject(CLSID_HTMLDocument, CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
  4061. 0, IID_PPV_ARG(IClassFactory, &_pcfHTML));
  4062. if (SUCCEEDED(hres))
  4063. {
  4064. hres = _pcfHTML->LockServer(TRUE);
  4065. if (FAILED(hres))
  4066. {
  4067. _pcfHTML->Release();
  4068. _pcfHTML = NULL;
  4069. return hres;
  4070. }
  4071. }
  4072. else
  4073. {
  4074. return hres;
  4075. }
  4076. }
  4077. TraceMsg(DM_COCREATEHTML, "CBB::_OnCoCreateDoc creating an instance (this=%x)", this);
  4078. hres = _pcfHTML->CreateInstance(NULL, IID_PPV_ARG(IUnknown, &pvarargOut->punkVal));
  4079. if (SUCCEEDED(hres))
  4080. {
  4081. pvarargOut->vt = VT_UNKNOWN;
  4082. }
  4083. else
  4084. {
  4085. pvarargOut->vt = VT_EMPTY;
  4086. }
  4087. return hres;
  4088. }
  4089. // fill a buffer with a variant, return a pointer to that buffer on success of the conversion
  4090. LPCTSTR VariantToString(const VARIANT *pv, LPTSTR pszBuf, UINT cch)
  4091. {
  4092. *pszBuf = 0;
  4093. if (pv && pv->vt == VT_BSTR && pv->bstrVal)
  4094. {
  4095. StrCpyN(pszBuf, pv->bstrVal, cch);
  4096. if (*pszBuf)
  4097. return pszBuf;
  4098. }
  4099. return NULL;
  4100. }
  4101. HRESULT CBaseBrowser2::Exec(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt,
  4102. VARIANTARG *pvarargIn, VARIANTARG *pvarargOut)
  4103. {
  4104. HRESULT hres = OLECMDERR_E_NOTSUPPORTED;
  4105. if (pguidCmdGroup == NULL)
  4106. {
  4107. switch(nCmdID)
  4108. {
  4109. case OLECMDID_CLOSE:
  4110. HWND hwnd;
  4111. GetWindow(&hwnd);
  4112. PostMessage(hwnd, WM_CLOSE, 0, 0);
  4113. hres = S_OK;
  4114. break;
  4115. // CBaseBrowser2 doesn't actually do the toolbar -- itbar does, forward this
  4116. case OLECMDID_UPDATECOMMANDS:
  4117. _NotifyCommandStateChange();
  4118. hres = S_OK;
  4119. break;
  4120. case OLECMDID_SETDOWNLOADSTATE:
  4121. ASSERT(pvarargIn);
  4122. if (pvarargIn)
  4123. {
  4124. _setDescendentNavigate(pvarargIn);
  4125. hres = _updateNavigationUI();
  4126. }
  4127. else
  4128. {
  4129. hres = E_INVALIDARG;
  4130. }
  4131. break;
  4132. case OLECMDID_REFRESH:
  4133. if (_bbd._pctView) // we must check!
  4134. hres = _bbd._pctView->Exec(NULL, nCmdID, nCmdexecopt, pvarargIn, pvarargOut);
  4135. else if (_bbd._psv)
  4136. {
  4137. _bbd._psv->Refresh();
  4138. hres = S_OK;
  4139. }
  4140. break;
  4141. //
  4142. // When Exec(OLECMDID_STOP) is called either by the containee (the
  4143. // current document) or the automation service object, we cancel
  4144. // the pending navigation (if any), then tell the current document
  4145. // to stop the go-going download in that page.
  4146. //
  4147. case OLECMDID_STOP:
  4148. // cant stop if we are modeless
  4149. if (S_FALSE == _DisableModeless())
  4150. {
  4151. LPITEMIDLIST pidlIntended = (_bbd._pidlPending) ? ILClone(_bbd._pidlPending) : NULL;
  4152. _CancelPendingNavigation();
  4153. // the _bbd._pctView gives us a _StopCurrentView()
  4154. _pbsOuter->_ExecChildren(_bbd._pctView, TRUE, NULL, OLECMDID_STOP, OLECMDEXECOPT_DONTPROMPTUSER, NULL, NULL); // Exec
  4155. if (!_bbd._pidlCur)
  4156. {
  4157. TCHAR szResURL[MAX_URL_STRING];
  4158. hres = MLBuildResURLWrap(TEXT("shdoclc.dll"),
  4159. HINST_THISDLL,
  4160. ML_CROSSCODEPAGE,
  4161. TEXT("navcancl.htm"),
  4162. szResURL,
  4163. ARRAYSIZE(szResURL),
  4164. TEXT("shdocvw.dll"));
  4165. if (SUCCEEDED(hres))
  4166. {
  4167. _ShowBlankPage(szResURL, pidlIntended);
  4168. }
  4169. }
  4170. if (pidlIntended)
  4171. {
  4172. ILFree(pidlIntended);
  4173. }
  4174. }
  4175. hres = S_OK;
  4176. break;
  4177. // handled in basesb so IWebBrowser::ExecWB gets this
  4178. // since this used to be in shbrowse, make sure we do
  4179. // it only if _fTopBrowser
  4180. case OLECMDID_FIND:
  4181. #define TBIDM_SEARCH 0x123 // defined in browseui\itbdrop.h
  4182. // Check restriction here cuz Win95 didn't check in SHFindFiles like it now does.
  4183. if (!SHRestricted(REST_NOFIND) && _fTopBrowser)
  4184. {
  4185. if (!_bbd._pctView || FAILED(_bbd._pctView->Exec(NULL, nCmdID, nCmdexecopt, pvarargIn, pvarargOut)))
  4186. {
  4187. if (pvarargIn && pvarargIn->vt == VT_UNKNOWN)
  4188. {
  4189. ASSERT(pvarargIn->punkVal);
  4190. VARIANT var = {0};
  4191. var.vt = VT_I4;
  4192. var.lVal = -1;
  4193. if (SUCCEEDED(IUnknown_Exec(pvarargIn->punkVal, &CLSID_CommonButtons, TBIDM_SEARCH, 0, NULL, &var)))
  4194. break;
  4195. }
  4196. SHFindFiles(_bbd._pidlCur, NULL);
  4197. }
  4198. }
  4199. break;
  4200. case OLECMDID_HTTPEQUIV_DONE:
  4201. case OLECMDID_HTTPEQUIV:
  4202. hres = OnHttpEquiv(_bbd._psv, (OLECMDID_HTTPEQUIV_DONE == nCmdID), pvarargIn, pvarargOut);
  4203. break;
  4204. case OLECMDID_PREREFRESH:
  4205. // Tell the shell's HTML window we have a new document
  4206. // Fall through default
  4207. if (_phtmlWS)
  4208. {
  4209. _phtmlWS->ViewActivated();
  4210. }
  4211. // Binder prints by reflecting the print back down. do the same here
  4212. // Note: we may want to do the same for _PRINTPREVIEW, _PROPERTIES, _STOP, etc.
  4213. // The null command group should all go down, no need to stop these at the pass.
  4214. default:
  4215. if (_bbd._pctView) // we must check!
  4216. hres = _bbd._pctView->Exec(NULL, nCmdID, nCmdexecopt, pvarargIn, pvarargOut);
  4217. else
  4218. hres = OLECMDERR_E_NOTSUPPORTED;
  4219. break;
  4220. }
  4221. }
  4222. else if (IsEqualGUID(CGID_MSHTML, *pguidCmdGroup))
  4223. {
  4224. if (_bbd._pctView) // we must check!
  4225. hres = _bbd._pctView->Exec(&CGID_MSHTML, nCmdID, nCmdexecopt, pvarargIn, pvarargOut);
  4226. else
  4227. hres = OLECMDERR_E_NOTSUPPORTED;
  4228. }
  4229. else if (IsEqualGUID(CGID_Explorer, *pguidCmdGroup))
  4230. {
  4231. switch(nCmdID)
  4232. {
  4233. case SBCMDID_CREATESHORTCUT:
  4234. if ( pvarargIn
  4235. && (V_VT(pvarargIn) == VT_UNKNOWN)
  4236. )
  4237. {
  4238. _CreateShortcutOnDesktop(V_UNKNOWN(pvarargIn), nCmdexecopt & OLECMDEXECOPT_PROMPTUSER);
  4239. }
  4240. else
  4241. {
  4242. _CreateShortcutOnDesktop(NULL, nCmdexecopt & OLECMDEXECOPT_PROMPTUSER);
  4243. }
  4244. hres = S_OK;
  4245. break;
  4246. case SBCMDID_ADDTOFAVORITES:
  4247. {
  4248. LPITEMIDLIST pidl = NULL;
  4249. //if someone doesn't pass a path in, _AddToFavorites will use the current page
  4250. if ((pvarargIn != NULL) && (pvarargIn->vt == VT_BSTR))
  4251. IECreateFromPath(pvarargIn->bstrVal, &pidl);
  4252. TCHAR szTitle[128];
  4253. LPTSTR pszTitle = NULL;
  4254. if (pvarargOut)
  4255. pszTitle = (LPTSTR)VariantToString(pvarargOut, szTitle, ARRAYSIZE(szTitle)); // may be NULL
  4256. else
  4257. {
  4258. if (_bbd._pszTitleCur)
  4259. pszTitle = StrCpyNW(szTitle, _bbd._pszTitleCur, ARRAYSIZE(szTitle));
  4260. }
  4261. _AddToFavorites(pidl, pszTitle, nCmdexecopt & OLECMDEXECOPT_PROMPTUSER);
  4262. if (pidl)
  4263. ILFree(pidl);
  4264. hres = S_OK;
  4265. }
  4266. break;
  4267. case SBCMDID_OPTIONS:
  4268. _DoOptions(pvarargIn);
  4269. break;
  4270. case SBCMDID_CANCELNAVIGATION:
  4271. TraceMsg(DM_NAV, "ief NAV::%s called when _bbd._pidlCur==%x, _bbd._psvPending==%x",
  4272. TEXT("Exec(SBCMDID_CANCELNAV) called"),
  4273. _bbd._pidlCur, _bbd._psvPending);
  4274. // Check if this is sync or async
  4275. if (pvarargIn && pvarargIn->vt == VT_I4 && pvarargIn->lVal)
  4276. {
  4277. TraceMsg(DM_WEBCHECKDRT, "CBB::Exec calling _CancelPendingNavigation");
  4278. _CancelPendingNavigation();
  4279. }
  4280. else
  4281. {
  4282. //
  4283. // We must call ASYNC version in this case because this call
  4284. // is from the pending view itself.
  4285. //
  4286. LPITEMIDLIST pidlIntended = (_bbd._pidlPending) ? ILClone(_bbd._pidlPending) : NULL;
  4287. _CancelPendingNavigationAsync();
  4288. if (!_bbd._pidlCur)
  4289. {
  4290. if (!_fDontShowNavCancelPage)
  4291. {
  4292. TCHAR szResURL[MAX_URL_STRING];
  4293. if (IsGlobalOffline())
  4294. {
  4295. hres = MLBuildResURLWrap(TEXT("shdoclc.dll"),
  4296. HINST_THISDLL,
  4297. ML_CROSSCODEPAGE,
  4298. TEXT("offcancl.htm"),
  4299. szResURL,
  4300. ARRAYSIZE(szResURL),
  4301. TEXT("shdocvw.dll"));
  4302. if (SUCCEEDED(hres))
  4303. {
  4304. _ShowBlankPage(szResURL, pidlIntended);
  4305. }
  4306. }
  4307. else
  4308. {
  4309. hres = MLBuildResURLWrap(TEXT("shdoclc.dll"),
  4310. HINST_THISDLL,
  4311. ML_CROSSCODEPAGE,
  4312. TEXT("navcancl.htm"),
  4313. szResURL,
  4314. ARRAYSIZE(szResURL),
  4315. TEXT("shdocvw.dll"));
  4316. if (SUCCEEDED(hres))
  4317. {
  4318. _ShowBlankPage(szResURL, pidlIntended);
  4319. }
  4320. }
  4321. }
  4322. else
  4323. {
  4324. _fDontShowNavCancelPage = FALSE;
  4325. }
  4326. }
  4327. if (pidlIntended)
  4328. ILFree(pidlIntended);
  4329. }
  4330. hres = S_OK;
  4331. break;
  4332. case SBCMDID_ASYNCNAVIGATION:
  4333. TraceMsg(DM_NAV, "ief NAV::%s called when _bbd._pidlCur==%x, _bbd._psvPending==%x",
  4334. TEXT("Exec(SBCMDID_ASYNCNAV) called"),
  4335. _bbd._pidlCur, _bbd._psvPending);
  4336. //
  4337. // We must call ASYNC version in this case because this call
  4338. // is from the pending view itself.
  4339. //
  4340. _SendAsyncNavigationMsg(pvarargIn);
  4341. hres = S_OK;
  4342. break;
  4343. case SBCMDID_COCREATEDOCUMENT:
  4344. hres = _OnCoCreateDocument(pvarargOut);
  4345. break;
  4346. case SBCMDID_HISTSFOLDER:
  4347. if (pvarargOut)
  4348. {
  4349. VariantClearLazy(pvarargOut);
  4350. if (NULL == _punkSFHistory)
  4351. {
  4352. IHistSFPrivate *phsfHistory;
  4353. hres = LoadHistoryShellFolder(NULL, &phsfHistory);
  4354. if (SUCCEEDED(hres))
  4355. {
  4356. hres = phsfHistory->QueryInterface(IID_PPV_ARG(IUnknown, &_punkSFHistory));
  4357. phsfHistory->Release();
  4358. }
  4359. }
  4360. if (NULL != _punkSFHistory)
  4361. {
  4362. pvarargOut->vt = VT_UNKNOWN;
  4363. pvarargOut->punkVal = _punkSFHistory;
  4364. _punkSFHistory->AddRef();
  4365. }
  4366. }
  4367. break;
  4368. case SBCMDID_UPDATETRAVELLOG:
  4369. {
  4370. BOOL fForceUpdate = FALSE;
  4371. if (pvarargIn && (VT_I4 == V_VT(pvarargIn)))
  4372. {
  4373. _fIsLocalAnchor = !!(V_I4(pvarargIn) & TRAVELLOG_LOCALANCHOR);
  4374. fForceUpdate = !!(V_I4(pvarargIn) & TRAVELLOG_FORCEUPDATE);
  4375. }
  4376. _UpdateTravelLog(fForceUpdate);
  4377. }
  4378. // fall through
  4379. case SBCMDID_REPLACELOCATION:
  4380. if (pvarargIn && pvarargIn->vt == VT_BSTR)
  4381. {
  4382. WCHAR wzParsedUrl[MAX_URL_STRING];
  4383. LPWSTR pszUrl = pvarargIn->bstrVal;
  4384. LPITEMIDLIST pidl;
  4385. // BSTRs can be NULL.
  4386. if (!pszUrl)
  4387. pszUrl = L"";
  4388. // NOTE: This URL came from the user, so we need to clean it up.
  4389. // If the user entered "yahoo.com" or "Search Get Rich Quick",
  4390. // it will be turned into a search URL by ParseURLFromOutsideSourceW().
  4391. DWORD cchParsedUrl = ARRAYSIZE(wzParsedUrl);
  4392. if (!ParseURLFromOutsideSourceW(pszUrl, wzParsedUrl, &cchParsedUrl, NULL))
  4393. {
  4394. StrCpyN(wzParsedUrl, pszUrl, ARRAYSIZE(wzParsedUrl));
  4395. }
  4396. IEParseDisplayName(CP_ACP, wzParsedUrl, &pidl);
  4397. if (pidl)
  4398. {
  4399. NotifyRedirect(_bbd._psv, pidl, NULL);
  4400. ILFree(pidl);
  4401. }
  4402. }
  4403. // even if there was no url, still force no refresh.
  4404. _fGeneratedPage = TRUE;
  4405. // force updating the back and forward buttons
  4406. _pbsOuter->UpdateBackForwardState();
  4407. hres = S_OK;
  4408. break;
  4409. case SBCMDID_ONCLOSE:
  4410. hres = S_OK;
  4411. if (_bbd._pctView)
  4412. {
  4413. hres = _bbd._pctView->Exec(pguidCmdGroup, nCmdID, 0, NULL, NULL);
  4414. }
  4415. break;
  4416. case SBCMDID_SETSECURELOCKICON:
  4417. {
  4418. // if this is a SET, then just obey.
  4419. LONG lock = pvarargIn->lVal;
  4420. TraceMsg(DM_SSL, "SB::Exec() SETSECURELOCKICON lock = %d", lock);
  4421. if (lock >= SECURELOCK_FIRSTSUGGEST)
  4422. {
  4423. //
  4424. // if this was ever secure, then the lowest we can be
  4425. // suggested to is MIXED. otherwise we just choose the
  4426. // lowest level of security suggested.
  4427. //
  4428. if ((lock == SECURELOCK_SUGGEST_UNSECURE) &&
  4429. (_bbd._eSecureLockIcon != SECURELOCK_SET_UNSECURE))
  4430. {
  4431. lock = SECURELOCK_SET_MIXED;
  4432. }
  4433. else
  4434. {
  4435. lock = min(lock - SECURELOCK_FIRSTSUGGEST, _bbd._eSecureLockIcon);
  4436. }
  4437. }
  4438. UpdateSecureLockIcon(lock);
  4439. hres = S_OK;
  4440. }
  4441. break;
  4442. default:
  4443. hres = OLECMDERR_E_NOTSUPPORTED;
  4444. break;
  4445. }
  4446. }
  4447. else if (IsEqualGUID(CGID_ShellDocView, *pguidCmdGroup))
  4448. {
  4449. switch(nCmdID)
  4450. {
  4451. case SHDVID_GOBACK:
  4452. hres = _psbOuter->BrowseObject(NULL, SBSP_NAVIGATEBACK);
  4453. break;
  4454. case SHDVID_GOFORWARD:
  4455. hres = _psbOuter->BrowseObject(NULL, SBSP_NAVIGATEFORWARD);
  4456. break;
  4457. // we reflect AMBIENTPROPCHANGE down because this is how iedisp notifies dochost
  4458. // that an ambient property has changed. we don't need to reflect this down in
  4459. // cwebbrowsersb because only the top-level iwebbrowser2 is allowed to change props
  4460. case SHDVID_AMBIENTPROPCHANGE:
  4461. case SHDVID_PRINTFRAME:
  4462. case SHDVID_MIMECSETMENUOPEN:
  4463. case SHDVID_FONTMENUOPEN:
  4464. case SHDVID_DOCFAMILYCHARSET:
  4465. if (_bbd._pctView) // we must check!
  4466. {
  4467. hres = _bbd._pctView->Exec(pguidCmdGroup, nCmdID, nCmdexecopt, pvarargIn, pvarargOut);
  4468. }
  4469. else
  4470. hres = E_FAIL;
  4471. break;
  4472. case SHDVID_DEACTIVATEMENOW:
  4473. if (!_bbd._psvPending)
  4474. {
  4475. hres = S_OK;
  4476. break;
  4477. }
  4478. // fall through to activate new view
  4479. #ifdef FEATURE_PICS
  4480. case SHDVID_ACTIVATEMENOW:
  4481. #endif
  4482. if ( pvarargIn
  4483. && (VT_BOOL == V_VT(pvarargIn))
  4484. && (VARIANT_TRUE == V_BOOL(pvarargIn))) // Synchronous
  4485. {
  4486. if (_bbd._psvPending)
  4487. {
  4488. ASSERT(_pbsOuter);
  4489. _pbsOuter->ActivatePendingView();
  4490. }
  4491. }
  4492. else // Asynchronous
  4493. {
  4494. _ActivatePendingViewAsync();
  4495. }
  4496. hres = S_OK;
  4497. break;
  4498. case SHDVID_GETPENDINGOBJECT:
  4499. ASSERT( pvarargOut);
  4500. if (_bbd._psvPending && ((pvarargIn && pvarargIn->vt == VT_BOOL && pvarargIn->boolVal) || !_bbd._psv))
  4501. {
  4502. VariantClearLazy(pvarargOut);
  4503. _bbd._psvPending->QueryInterface(IID_PPV_ARG(IUnknown, &pvarargOut->punkVal));
  4504. if (pvarargOut->punkVal) pvarargOut->vt = VT_UNKNOWN;
  4505. }
  4506. hres = (pvarargOut->punkVal == NULL) ? E_FAIL : S_OK;
  4507. break;
  4508. case SHDVID_SETPRINTSTATUS:
  4509. if (pvarargIn && pvarargIn->vt == VT_BOOL)
  4510. {
  4511. VARIANTARG var = {0};
  4512. if (_bbd._pctView && SUCCEEDED(_bbd._pctView->Exec(&CGID_Explorer, SBCMDID_GETPANE, PANE_PRINTER, NULL, &var))
  4513. && V_UI4(&var) != PANE_NONE)
  4514. {
  4515. _psbOuter->SendControlMsg(FCW_STATUS, SB_SETICON, V_UI4(&var),
  4516. (LPARAM)(pvarargIn->boolVal ? g_hiconPrinter : NULL), NULL);
  4517. // we're putting the printer icon and the offline icon in the same
  4518. // slot on the status bar, so when we turn off the printer icon
  4519. // we have to check to see if we're offline so we can put the offline
  4520. // icon back
  4521. if (!pvarargIn->boolVal && IsGlobalOffline())
  4522. {
  4523. #ifdef DEBUG
  4524. VARIANTARG var2 = {0};
  4525. _bbd._pctView->Exec(&CGID_Explorer, SBCMDID_GETPANE, PANE_OFFLINE, NULL, &var2);
  4526. ASSERT(V_UI4(&var2) == V_UI4(&var));
  4527. #endif DEBUG
  4528. _psbOuter->SendControlMsg(FCW_STATUS, SB_SETICON, V_UI4(&var),
  4529. (LPARAM)(g_hiconOffline), NULL);
  4530. } // if (!pvarargIn->boolVal && IsGlobalOffline())
  4531. }
  4532. hres = S_OK;
  4533. }
  4534. else
  4535. hres = E_INVALIDARG;
  4536. break;
  4537. #ifdef FEATURE_PICS
  4538. /* Dochost sends up this command to have us put up the PICS access
  4539. * denied dialog. This is done so that all calls to this ratings
  4540. * API are modal to the top-level browser window; that in turn
  4541. * lets the ratings code coalesce denials for all subframes into
  4542. * a single dialog.
  4543. */
  4544. case SHDVID_PICSBLOCKINGUI:
  4545. {
  4546. void * pDetails;
  4547. if (pvarargIn && pvarargIn->vt == VT_INT_PTR)
  4548. pDetails = pvarargIn->byref;
  4549. else
  4550. pDetails = NULL;
  4551. TraceMsg(DM_PICS, "CBaseBrowser2::Exec calling RatingAccessDeniedDialog2");
  4552. /**
  4553. * We QueryService for an SID_IRatingNotification which is
  4554. * implemented by our host, if we find it, instead of
  4555. * displaying the modal ratings dialog, we notify our host through
  4556. * the interface and allow it to make the decision
  4557. */
  4558. IRatingNotification* pRatingNotify;
  4559. hres = QueryService(SID_SRatingNotification, IID_PPV_ARG(IRatingNotification, &pRatingNotify));
  4560. if (SUCCEEDED(hres))
  4561. {
  4562. RATINGBLOCKINGINFO* pRBInfo = NULL;
  4563. TraceMsg(DM_PICS, "CBaseBrowser2::Exec calling RatingMarsCrackData");
  4564. hres = RatingCustomCrackData(NULL, pDetails, &pRBInfo);
  4565. if (SUCCEEDED(hres))
  4566. {
  4567. hres = pRatingNotify->AccessDeniedNotify(pRBInfo);
  4568. RatingCustomDeleteCrackedData(pRBInfo);
  4569. }
  4570. pRatingNotify->Release();
  4571. } // if (SUCCEEDED(hres))
  4572. else {
  4573. hres = RatingAccessDeniedDialog2(_bbd._hwnd, NULL, pDetails);
  4574. }
  4575. }
  4576. break;
  4577. #endif
  4578. case SHDVID_ONCOLORSCHANGE:
  4579. // PALETTE:
  4580. // PALETTE: recompute our palette
  4581. // PALETTE:
  4582. _ColorsDirty(BPT_UnknownPalette);
  4583. break;
  4584. case SHDVID_GETOPTIONSHWND:
  4585. {
  4586. ASSERT(pvarargOut != NULL);
  4587. ASSERT(V_VT(pvarargOut) == VT_BYREF);
  4588. // return the hwnd for the inet options
  4589. // modal prop sheet. we're tracking
  4590. // this hwnd because if it's open
  4591. // and plugUI shutdown needs to happen,
  4592. // that dialog needs to receive a WM_CLOSE
  4593. // before we can nuke it
  4594. hres = E_FAIL;
  4595. // is there a list of window handles?
  4596. ENTERCRITICAL;
  4597. if (s_hdpaOptionsHwnd != NULL)
  4598. {
  4599. int cPtr = DPA_GetPtrCount(s_hdpaOptionsHwnd);
  4600. // is that list nonempty?
  4601. if (cPtr > 0)
  4602. {
  4603. HWND hwndOptions = (HWND)DPA_GetPtr(s_hdpaOptionsHwnd, 0);
  4604. ASSERT(hwndOptions != NULL);
  4605. pvarargOut->byref = hwndOptions;
  4606. // remove it from the list
  4607. // that hwnd is not our responsibility anymore
  4608. DPA_DeletePtr(s_hdpaOptionsHwnd, 0);
  4609. // successful hwnd retrieval
  4610. hres = S_OK;
  4611. }
  4612. }
  4613. LEAVECRITICAL;
  4614. }
  4615. break;
  4616. case SHDVID_DISPLAYSCRIPTERRORS:
  4617. {
  4618. HRESULT hr;
  4619. hr = _bbd._pctView->Exec(pguidCmdGroup, nCmdID, nCmdexecopt, pvarargIn, pvarargOut);
  4620. return hr;
  4621. }
  4622. break;
  4623. case SHDVID_NAVIGATEFROMDOC: // The document called Navigate
  4624. _dwDocFlags |= DOCFLAG_NAVIGATEFROMDOC;
  4625. return S_OK;
  4626. case SHDVID_SETNAVIGATABLECODEPAGE:
  4627. _dwDocFlags |= DOCFLAG_SETNAVIGATABLECODEPAGE;
  4628. return S_OK;
  4629. case SHDVID_CHECKINCACHEIFOFFLINE:
  4630. {
  4631. if (pvarargIn && (VT_BSTR == V_VT(pvarargIn)) && V_BSTR(pvarargIn)
  4632. && pvarargOut && (VT_BOOL == V_VT(pvarargOut)))
  4633. {
  4634. LPITEMIDLIST pidl = PidlFromUrl(V_BSTR(pvarargIn));
  4635. if (pidl)
  4636. {
  4637. // (scotrobe): We should be passing fIsPost
  4638. // into _CheckInCacheIfOffline.
  4639. //
  4640. V_BOOL(pvarargOut) = (S_OK == _CheckInCacheIfOffline(pidl, FALSE));
  4641. ILFree(pidl);
  4642. return S_OK;
  4643. }
  4644. }
  4645. return E_FAIL;
  4646. }
  4647. break;
  4648. case SHDVID_CHECKDONTUPDATETLOG:
  4649. {
  4650. if (pvarargOut)
  4651. {
  4652. V_VT(pvarargOut) = VT_BOOL;
  4653. V_BOOL(pvarargOut) = (_fDontAddTravelEntry ? VARIANT_TRUE : VARIANT_FALSE);
  4654. hres = S_OK;
  4655. }
  4656. break;
  4657. }
  4658. case SHDVID_FIREFILEDOWNLOAD:
  4659. if (pvarargOut)
  4660. {
  4661. BOOL fCancel = FALSE;
  4662. V_VT(pvarargOut) = VT_BOOL;
  4663. FireEvent_FileDownload(_bbd._pautoEDS, &fCancel, pvarargIn ? V_BOOL(pvarargIn):VARIANT_FALSE);
  4664. pvarargOut->boolVal = (fCancel ? VARIANT_TRUE : VARIANT_FALSE);
  4665. hres = S_OK;
  4666. }
  4667. break;
  4668. default:
  4669. hres = OLECMDERR_E_NOTSUPPORTED;
  4670. break;
  4671. }
  4672. }
  4673. else if (IsEqualGUID(CGID_ShortCut, *pguidCmdGroup))
  4674. {
  4675. if (_bbd._pctView) // we must check!
  4676. hres = _bbd._pctView->Exec(&CGID_ShortCut, nCmdID, nCmdexecopt, pvarargIn, pvarargOut);
  4677. else
  4678. hres = OLECMDERR_E_NOTSUPPORTED;
  4679. }
  4680. else if (IsEqualGUID(CGID_DocHostCmdPriv, *pguidCmdGroup))
  4681. {
  4682. switch(nCmdID)
  4683. {
  4684. case DOCHOST_DOCCANNAVIGATE:
  4685. if (pvarargIn && VT_UNKNOWN == V_VT(pvarargIn) && V_UNKNOWN(pvarargIn))
  4686. {
  4687. _dwDocFlags |= DOCFLAG_DOCCANNAVIGATE;
  4688. }
  4689. else
  4690. {
  4691. _dwDocFlags &= ~DOCFLAG_DOCCANNAVIGATE;
  4692. }
  4693. hres = S_OK;
  4694. break;
  4695. case DOCHOST_SETBROWSERINDEX:
  4696. if (pvarargIn && VT_I4 == V_VT(pvarargIn))
  4697. {
  4698. _dwBrowserIndex = V_I4(pvarargIn);
  4699. return S_OK;
  4700. }
  4701. return E_INVALIDARG;
  4702. default:
  4703. hres = OLECMDERR_E_UNKNOWNGROUP; // Backwards compatability
  4704. break;
  4705. }
  4706. }
  4707. else if (IsEqualGUID(CGID_InternetExplorer, *pguidCmdGroup))
  4708. {
  4709. switch(nCmdID)
  4710. {
  4711. case IECMDID_SET_INVOKE_DEFAULT_BROWSER_ON_NEW_WINDOW:
  4712. if ((NULL != pvarargIn) && (pvarargIn->vt == VT_BOOL))
  4713. {
  4714. _fInvokeDefBrowserOnNewWindow = pvarargIn->boolVal ? TRUE : FALSE;
  4715. hres = S_OK;
  4716. }
  4717. else
  4718. {
  4719. hres = E_INVALIDARG;
  4720. }
  4721. break;
  4722. case IECMDID_GET_INVOKE_DEFAULT_BROWSER_ON_NEW_WINDOW:
  4723. if ((NULL != pvarargOut) && (pvarargOut->vt == VT_EMPTY))
  4724. {
  4725. pvarargOut->vt = VT_BOOL;
  4726. pvarargOut->boolVal = _fInvokeDefBrowserOnNewWindow ? TRUE : FALSE;
  4727. hres = S_OK;
  4728. }
  4729. else
  4730. {
  4731. hres = E_INVALIDARG;
  4732. }
  4733. break;
  4734. case IECMDID_BEFORENAVIGATE_GETSHELLBROWSE:
  4735. {
  4736. // true if pending navigate is NOT a web navigation.
  4737. if (pvarargOut && _pidlBeforeNavigateEvent)
  4738. {
  4739. DWORD dwAttributes = SFGAO_FOLDER;
  4740. hres = IEGetAttributesOf(_pidlBeforeNavigateEvent, &dwAttributes);
  4741. V_VT(pvarargOut) = VT_BOOL;
  4742. V_BOOL(pvarargOut) = SUCCEEDED(hres) && (dwAttributes & SFGAO_FOLDER) ?
  4743. VARIANT_TRUE : VARIANT_FALSE;
  4744. hres = S_OK;
  4745. }
  4746. }
  4747. break;
  4748. case IECMDID_BEFORENAVIGATE_DOEXTERNALBROWSE:
  4749. {
  4750. if (_pidlBeforeNavigateEvent)
  4751. {
  4752. hres = _psbOuter->BrowseObject(_pidlBeforeNavigateEvent, SBSP_ABSOLUTE | SBSP_NEWBROWSER);
  4753. }
  4754. }
  4755. break;
  4756. case IECMDID_BEFORENAVIGATE_GETIDLIST:
  4757. {
  4758. if (pvarargOut && _pidlBeforeNavigateEvent)
  4759. {
  4760. hres = InitVariantFromIDList(pvarargOut, _pidlBeforeNavigateEvent);
  4761. }
  4762. }
  4763. break;
  4764. default:
  4765. hres = OLECMDERR_E_NOTSUPPORTED;
  4766. break;
  4767. }
  4768. }
  4769. else
  4770. {
  4771. hres = OLECMDERR_E_UNKNOWNGROUP;
  4772. }
  4773. return hres;
  4774. }
  4775. LPITEMIDLIST
  4776. CBaseBrowser2::PidlFromUrl(BSTR bstrUrl)
  4777. {
  4778. LPITEMIDLIST pidl = NULL;
  4779. ASSERT(bstrUrl);
  4780. IEParseDisplayNameWithBCW(CP_ACP, bstrUrl, NULL, &pidl);
  4781. // IEParseDisplayNameWithBCW will return a null pidl if
  4782. // the URL has any kind of fragment identifier at the
  4783. // end - #, ? =, etc.
  4784. //
  4785. if (!pidl)
  4786. {
  4787. TCHAR szPath[INTERNET_MAX_URL_LENGTH + 1];
  4788. DWORD cchBuf = ARRAYSIZE(szPath);
  4789. // If it's a FILE URL, convert it to a path.
  4790. //
  4791. if (IsFileUrlW(bstrUrl) && SUCCEEDED(PathCreateFromUrl(bstrUrl, szPath, &cchBuf, 0)))
  4792. {
  4793. // That worked, we are done because our buffer is now full.
  4794. }
  4795. else
  4796. {
  4797. // We now need to copy to the buffer and we assume it's a path.
  4798. //
  4799. StrCpyN(szPath, bstrUrl, ARRAYSIZE(szPath));
  4800. }
  4801. pidl = SHSimpleIDListFromPath(szPath);
  4802. }
  4803. return pidl;
  4804. }
  4805. BSTR
  4806. CBaseBrowser2::GetHTMLWindowUrl(IHTMLWindow2 * pHTMLWindow)
  4807. {
  4808. BSTR bstrUrl = NULL;
  4809. IHTMLPrivateWindow * pPrivateWindow;
  4810. HRESULT hr = pHTMLWindow->QueryInterface(IID_PPV_ARG(IHTMLPrivateWindow, &pPrivateWindow));
  4811. if (SUCCEEDED(hr))
  4812. {
  4813. pPrivateWindow->GetAddressBarUrl(&bstrUrl);
  4814. pPrivateWindow->Release();
  4815. }
  4816. return bstrUrl;
  4817. }
  4818. LPITEMIDLIST
  4819. CBaseBrowser2::_GetPidlForDisplay(BSTR bstrUrl, BOOL * pfIsErrorUrl /* = NULL */)
  4820. {
  4821. BOOL fIsErrorUrl = FALSE;
  4822. LPITEMIDLIST pidl = NULL;
  4823. if (bstrUrl)
  4824. {
  4825. fIsErrorUrl = ::IsErrorUrl(bstrUrl);
  4826. if (!fIsErrorUrl)
  4827. {
  4828. pidl = PidlFromUrl(bstrUrl);
  4829. }
  4830. else
  4831. {
  4832. // Only strip the anchor fragment if it's not JAVASCRIPT: or VBSCRIPT:, because a # could not an
  4833. // anchor but a string to be evaluated by a script engine like #00ff00 for an RGB color.
  4834. //
  4835. int nScheme = GetUrlSchemeW(bstrUrl);
  4836. if (nScheme != URL_SCHEME_JAVASCRIPT && nScheme != URL_SCHEME_VBSCRIPT)
  4837. {
  4838. // Locate local anchor fragment if possible
  4839. //
  4840. LPWSTR pszFragment = StrChr(bstrUrl, L'#');
  4841. // It is possible to have a fragment identifier
  4842. // with no corresponding fragment.
  4843. //
  4844. if (pszFragment && lstrlen(pszFragment) > 1)
  4845. {
  4846. BSTR bstrTemp = SysAllocString(pszFragment+1);
  4847. if (bstrTemp)
  4848. {
  4849. pidl = PidlFromUrl(bstrTemp);
  4850. SysFreeString(bstrTemp);
  4851. }
  4852. }
  4853. }
  4854. }
  4855. }
  4856. if (pfIsErrorUrl)
  4857. *pfIsErrorUrl = fIsErrorUrl;
  4858. return pidl;
  4859. }
  4860. HRESULT CBaseBrowser2::ParseDisplayName(IBindCtx *pbc, LPOLESTR pszDisplayName,
  4861. ULONG *pchEaten, IMoniker **ppmkOut)
  4862. {
  4863. TraceMsg(0, "sdv TR ::ParseDisplayName called");
  4864. *ppmkOut = NULL;
  4865. return E_NOTIMPL;
  4866. }
  4867. HRESULT CBaseBrowser2::EnumObjects( DWORD grfFlags, IEnumUnknown **ppenum)
  4868. {
  4869. TraceMsg(0, "sdv TR ::EnumObjects called");
  4870. *ppenum = NULL;
  4871. return E_NOTIMPL;
  4872. }
  4873. HRESULT CBaseBrowser2::LockContainer( BOOL fLock)
  4874. {
  4875. TraceMsg(0, "sdv TR ::LockContainer called");
  4876. return E_NOTIMPL;
  4877. }
  4878. HRESULT CBaseBrowser2::SetTitle(IShellView* psv, LPCWSTR lpszName)
  4879. {
  4880. LPWSTR *ppszName = NULL;
  4881. BOOL fFireEvent = FALSE;
  4882. LPITEMIDLIST pidl;
  4883. // We need to forward title changes on to the automation interface.
  4884. // But since title changes can technically occur at any time we need
  4885. // to distinguish between current and pending title changes and only
  4886. // pass on the current title change now. We'll pass on the pending
  4887. // title change at NavigateComplete time. (This also lets us identify
  4888. // when we navigate to non-SetTitle object (such as the shell) and
  4889. // simulate a TitleChange event.)
  4890. //
  4891. // Since the DocObjectHost needs to retrieve the title later, we
  4892. // hold onto the current view's title change so they don't have to.
  4893. //
  4894. // Figure out which object is changing.
  4895. //
  4896. if (IsSameObject(_bbd._psv, psv))
  4897. {
  4898. ppszName = &_bbd._pszTitleCur;
  4899. pidl = _bbd._pidlCur;
  4900. fFireEvent = TRUE;
  4901. }
  4902. else if (EVAL(IsSameObject(_bbd._psvPending, psv) || !_bbd._psvPending)) // no pending probably means we're in _MayPlayTransition
  4903. {
  4904. ppszName = &_bbd._pszTitlePending;
  4905. pidl = _bbd._pidlPending;
  4906. // If we have no current guy, might as well set the title early
  4907. fFireEvent = !_bbd._psv;
  4908. }
  4909. else
  4910. {
  4911. ppszName = NULL;
  4912. pidl = NULL; // init pidl to suppress bogus C4701 warning
  4913. }
  4914. if (ppszName)
  4915. {
  4916. UINT cchLen = lstrlenW(lpszName) + 1; // +1 for NULL
  4917. UINT cbAlloc;
  4918. // For some reason we cap the length of this string. We can't cap
  4919. // less than MAX_PATH because we need to handle filesys names.
  4920. //
  4921. if (cchLen > MAX_PATH)
  4922. cchLen = MAX_PATH;
  4923. // We want to allocate at least a medium size string because
  4924. // many web pages script the title one character at a time.
  4925. //
  4926. #define MIN_TITLE_ALLOC 64
  4927. if (cchLen < MIN_TITLE_ALLOC)
  4928. cbAlloc = MIN_TITLE_ALLOC * SIZEOF(*lpszName);
  4929. else
  4930. cbAlloc = cchLen * SIZEOF(*lpszName);
  4931. #undef MIN_TITLE_ALLOC
  4932. // Do we need to allocate?
  4933. if (!(*ppszName) || LocalSize((HLOCAL)(*ppszName)) < cbAlloc)
  4934. {
  4935. // Free up Old Title
  4936. if(*ppszName)
  4937. LocalFree((void *)(*ppszName));
  4938. *ppszName = (LPWSTR)LocalAlloc(LPTR, cbAlloc);
  4939. }
  4940. if (*ppszName)
  4941. {
  4942. StrCpyNW(*ppszName, lpszName, cchLen);
  4943. if (fFireEvent)
  4944. {
  4945. DWORD dwOptions;
  4946. FireEvent_DoInvokeStringW(_bbd._pautoEDS, DISPID_TITLECHANGE, *ppszName);
  4947. // If this is a desktop component, try to update the friendly name if necessary.
  4948. if (!_fCheckedDesktopComponentName)
  4949. {
  4950. _fCheckedDesktopComponentName = TRUE;
  4951. if (SUCCEEDED(GetTopFrameOptions(_pspOuter, &dwOptions)) && (dwOptions & FRAMEOPTIONS_DESKTOP))
  4952. {
  4953. WCHAR wszPath[MAX_URL_STRING];
  4954. if (SUCCEEDED(::IEGetDisplayName(pidl, wszPath, SHGDN_FORPARSING)))
  4955. {
  4956. UpdateDesktopComponentName(wszPath, lpszName);
  4957. }
  4958. }
  4959. }
  4960. }
  4961. }
  4962. }
  4963. return NOERROR;
  4964. }
  4965. HRESULT CBaseBrowser2::GetTitle(IShellView* psv, LPWSTR pszName, DWORD cchName)
  4966. {
  4967. LPWSTR psz;
  4968. if (!psv || IsSameObject(_bbd._psv, psv))
  4969. {
  4970. psz = _bbd._pszTitleCur;
  4971. }
  4972. else if (EVAL(IsSameObject(_bbd._psvPending, psv) || !_bbd._psvPending))
  4973. {
  4974. psz = _bbd._pszTitlePending;
  4975. }
  4976. else
  4977. {
  4978. psz = NULL;
  4979. }
  4980. if (psz)
  4981. {
  4982. StrCpyNW(pszName, psz, cchName);
  4983. return(S_OK);
  4984. }
  4985. else
  4986. {
  4987. *pszName = 0;
  4988. return(E_FAIL);
  4989. }
  4990. }
  4991. HRESULT CBaseBrowser2::GetParentSite(struct IOleInPlaceSite** ppipsite)
  4992. {
  4993. *ppipsite = NULL;
  4994. return E_NOTIMPL;
  4995. }
  4996. HRESULT CBaseBrowser2::GetOleObject(struct IOleObject** ppobjv)
  4997. {
  4998. *ppobjv = NULL;
  4999. return E_NOTIMPL;
  5000. }
  5001. HRESULT CBaseBrowser2::NotifyRedirect(IShellView * psv, LPCITEMIDLIST pidlNew, BOOL *pfDidBrowse)
  5002. {
  5003. HRESULT hres = E_FAIL;
  5004. if (pfDidBrowse)
  5005. *pfDidBrowse = FALSE;
  5006. if (IsSameObject(psv, _bbd._psv) ||
  5007. IsSameObject(psv, _bbd._psvPending))
  5008. {
  5009. hres = _pbsOuter->_TryShell2Rename(psv, pidlNew);
  5010. if (FAILED(hres))
  5011. {
  5012. // if we weren't able to just swap it, we've got to browse to it
  5013. // but pass redirect so that we don't add a navigation stack item
  5014. //
  5015. // NOTE: the above comment is a bit old since we don't pass
  5016. // redirect here. If we ever start passing redirect here,
  5017. // we'll confuse ISVs relying on the NavigateComplete event
  5018. // exactly mirroring when navigations enter the navigation stack.
  5019. //
  5020. hres = _psbOuter->BrowseObject(pidlNew, SBSP_WRITENOHISTORY | SBSP_SAMEBROWSER);
  5021. if(pfDidBrowse)
  5022. *pfDidBrowse = TRUE;
  5023. }
  5024. }
  5025. return hres;
  5026. }
  5027. HRESULT CBaseBrowser2::SetFlags(DWORD dwFlags, DWORD dwFlagMask)
  5028. {
  5029. if (dwFlagMask & BSF_REGISTERASDROPTARGET)
  5030. {
  5031. _fNoDragDrop = (!(dwFlags & BSF_REGISTERASDROPTARGET)) ? TRUE : FALSE;
  5032. if (!_fNoDragDrop)
  5033. _RegisterAsDropTarget();
  5034. else
  5035. _UnregisterAsDropTarget();
  5036. }
  5037. if (dwFlagMask & BSF_DONTSHOWNAVCANCELPAGE)
  5038. {
  5039. _fDontShowNavCancelPage = !!(dwFlags & BSF_DONTSHOWNAVCANCELPAGE);
  5040. }
  5041. if (dwFlagMask & BSF_HTMLNAVCANCELED)
  5042. {
  5043. _fHtmlNavCanceled = !!(dwFlags & BSF_HTMLNAVCANCELED);
  5044. }
  5045. return S_OK;
  5046. }
  5047. HRESULT CBaseBrowser2::GetFlags(DWORD *pdwFlags)
  5048. {
  5049. DWORD dwFlags = 0;
  5050. if (!_fNoDragDrop)
  5051. dwFlags |= BSF_REGISTERASDROPTARGET;
  5052. if (_fTopBrowser)
  5053. dwFlags |= BSF_TOPBROWSER;
  5054. if (_grfHLNFPending & HLNF_CREATENOHISTORY)
  5055. dwFlags |= BSF_NAVNOHISTORY;
  5056. if (_fHtmlNavCanceled)
  5057. dwFlags |= BSF_HTMLNAVCANCELED;
  5058. if (_dwDocFlags & DOCFLAG_SETNAVIGATABLECODEPAGE)
  5059. dwFlags |= BSF_SETNAVIGATABLECODEPAGE;
  5060. if (_dwDocFlags & DOCFLAG_NAVIGATEFROMDOC)
  5061. dwFlags |= BSF_DELEGATEDNAVIGATION;
  5062. *pdwFlags = dwFlags;
  5063. return S_OK;
  5064. }
  5065. HRESULT CBaseBrowser2::UpdateWindowList(void)
  5066. {
  5067. // code used to assert, but in WebBrowserOC cases we can get here.
  5068. return E_UNEXPECTED;
  5069. }
  5070. STDMETHODIMP CBaseBrowser2::IsControlWindowShown(UINT id, BOOL *pfShown)
  5071. {
  5072. if (pfShown)
  5073. *pfShown = FALSE;
  5074. return E_NOTIMPL;
  5075. }
  5076. STDMETHODIMP CBaseBrowser2::ShowControlWindow(UINT id, BOOL fShow)
  5077. {
  5078. return E_NOTIMPL;
  5079. }
  5080. HRESULT CBaseBrowser2::IEGetDisplayName(LPCITEMIDLIST pidl, LPWSTR pwszName, UINT uFlags)
  5081. {
  5082. return ::IEGetDisplayName(pidl, pwszName, uFlags);
  5083. }
  5084. HRESULT CBaseBrowser2::IEParseDisplayName(UINT uiCP, LPCWSTR pwszPath, LPITEMIDLIST * ppidlOut)
  5085. {
  5086. HRESULT hr;
  5087. IBindCtx * pbc = NULL;
  5088. WCHAR wzParsedUrl[MAX_URL_STRING];
  5089. //
  5090. // if we can find a search context living in a host somewhere,
  5091. // then we need to pass that into ParseUrlFromOutsideSource
  5092. // because it'll use it to customize the behavior of
  5093. // the search hooks if a search ends up happening
  5094. //
  5095. ISearchContext * pSC = NULL;
  5096. QueryService(SID_STopWindow, IID_PPV_ARG(ISearchContext, &pSC));
  5097. //
  5098. // NOTE: This URL came from the user, so we need to clean it up.
  5099. // If the user entered "yahoo.com" or "Search Get Rich Quick",
  5100. // it will be turned into a search URL by ParseURLFromOutsideSourceW().
  5101. //
  5102. DWORD cchParsedUrl = ARRAYSIZE(wzParsedUrl);
  5103. if (!ParseURLFromOutsideSourceWithContextW(pwszPath, wzParsedUrl, &cchParsedUrl, NULL, pSC))
  5104. {
  5105. StrCpyN(wzParsedUrl, pwszPath, ARRAYSIZE(wzParsedUrl));
  5106. }
  5107. if (pSC != NULL)
  5108. {
  5109. pSC->Release();
  5110. }
  5111. // This is currently used for FTP, so we only do it for FTP for perf reasons.
  5112. if (URL_SCHEME_FTP == GetUrlSchemeW(wzParsedUrl))
  5113. pbc = CreateBindCtxForUI(SAFECAST(this, IOleContainer *)); // We really want to cast to (IUnknown *) but that's ambiguous.
  5114. hr = IEParseDisplayNameWithBCW(uiCP, wzParsedUrl, pbc, ppidlOut);
  5115. ATOMICRELEASE(pbc);
  5116. return hr;
  5117. }
  5118. HRESULT _DisplayParseError(HWND hwnd, HRESULT hres, LPCWSTR pwszPath)
  5119. {
  5120. if (FAILED(hres)
  5121. && hres != E_OUTOFMEMORY
  5122. && hres != HRESULT_FROM_WIN32(ERROR_CANCELLED))
  5123. {
  5124. TCHAR szPath[MAX_URL_STRING];
  5125. SHUnicodeToTChar(pwszPath, szPath, ARRAYSIZE(szPath));
  5126. MLShellMessageBox(hwnd,
  5127. MAKEINTRESOURCE(IDS_ERROR_GOTO),
  5128. MAKEINTRESOURCE(IDS_TITLE),
  5129. MB_OK | MB_SETFOREGROUND | MB_ICONSTOP,
  5130. szPath);
  5131. hres = HRESULT_FROM_WIN32(ERROR_CANCELLED);
  5132. }
  5133. return hres;
  5134. }
  5135. HRESULT CBaseBrowser2::DisplayParseError(HRESULT hres, LPCWSTR pwszPath)
  5136. {
  5137. return _DisplayParseError(_bbd._hwnd, hres, pwszPath);
  5138. }
  5139. HRESULT CBaseBrowser2::_CheckZoneCrossing(LPCITEMIDLIST pidl)
  5140. {
  5141. if (!(_dwDocFlags & DOCFLAG_NAVIGATEFROMDOC))
  5142. {
  5143. return _pbsOuter->v_CheckZoneCrossing(pidl);
  5144. }
  5145. return S_OK;
  5146. }
  5147. // if in global offline mode and this item requires net access and it is
  5148. // not in the cache put up UI to go online.
  5149. //
  5150. // returns:
  5151. // S_OK URL is ready to be accessed
  5152. // E_ABORT user canceled the UI
  5153. HRESULT CBaseBrowser2::_CheckInCacheIfOffline(LPCITEMIDLIST pidl, BOOL fIsAPost)
  5154. {
  5155. HRESULT hr = S_OK; // assume it is
  5156. VARIANT_BOOL fFrameIsSilent;
  5157. VARIANT_BOOL fFrameHasAmbientOfflineMode;
  5158. EVAL(SUCCEEDED(_bbd._pautoWB2->get_Silent(&fFrameHasAmbientOfflineMode))); // should always work
  5159. EVAL(SUCCEEDED(_bbd._pautoWB2->get_Offline(&fFrameIsSilent)));
  5160. if ((fFrameIsSilent == VARIANT_FALSE) &&
  5161. (fFrameHasAmbientOfflineMode == VARIANT_FALSE)&&
  5162. pidl && (pidl != PIDL_NOTHING) && (pidl != PIDL_LOCALHISTORY) &&
  5163. IsBrowserFrameOptionsPidlSet(pidl, BFO_USE_IE_OFFLINE_SUPPORT) &&
  5164. IsGlobalOffline())
  5165. {
  5166. TCHAR szURL[MAX_URL_STRING];
  5167. EVAL(SUCCEEDED(::IEGetNameAndFlags(pidl, SHGDN_FORPARSING, szURL, SIZECHARS(szURL), NULL)));
  5168. if (UrlHitsNet(szURL) && ((!UrlIsMappedOrInCache(szURL)) || fIsAPost))
  5169. {
  5170. // UI to allow user to go on-line
  5171. HWND hParentWnd = NULL; // init to suppress bogus C4701 warning
  5172. hr = E_FAIL;
  5173. if(!_fTopBrowser)
  5174. {
  5175. IOleWindow *pOleWindow;
  5176. hr = _pspOuter->QueryService(SID_STopLevelBrowser, IID_PPV_ARG(IOleWindow, &pOleWindow));
  5177. if(SUCCEEDED(hr))
  5178. {
  5179. ASSERT(pOleWindow);
  5180. hr = pOleWindow->GetWindow(&hParentWnd);
  5181. pOleWindow->Release();
  5182. }
  5183. }
  5184. if (S_OK != hr)
  5185. {
  5186. hr = S_OK;
  5187. hParentWnd = _bbd._hwnd;
  5188. }
  5189. _psbOuter->EnableModelessSB(FALSE);
  5190. if (InternetGoOnline(szURL, hParentWnd, FALSE))
  5191. {
  5192. // Tell all browser windows to update their title and status pane
  5193. SendShellIEBroadcastMessage(WM_WININICHANGE,0,0, 1000);
  5194. }
  5195. else
  5196. hr = E_ABORT; // user abort case...
  5197. _psbOuter->EnableModelessSB(TRUE);
  5198. }
  5199. }
  5200. return hr;
  5201. }
  5202. // This function exists to prevent us from using the stack space too long.
  5203. // We will use it here and then free it when we return.
  5204. HRESULT CBaseBrowser2::_ReplaceWithGoHome(LPCITEMIDLIST * ppidl, LPITEMIDLIST * ppidlFree)
  5205. {
  5206. TCHAR szHome[MAX_URL_STRING];
  5207. HRESULT hres = _GetStdLocation(szHome, ARRAYSIZE(szHome), DVIDM_GOHOME);
  5208. if (SUCCEEDED(hres))
  5209. {
  5210. hres = IECreateFromPath(szHome, ppidlFree);
  5211. if (SUCCEEDED(hres))
  5212. {
  5213. *ppidl = *ppidlFree;
  5214. }
  5215. }
  5216. return hres;
  5217. }
  5218. // this does all the preliminary checking of whether we can navigate to pidl or not.
  5219. // then if all is ok, we do the navigate with CreateNewShellViewPidl
  5220. HRESULT CBaseBrowser2::_NavigateToPidl(LPCITEMIDLIST pidl, DWORD grfHLNF, DWORD fSBSP)
  5221. {
  5222. HRESULT hres;
  5223. BOOL fCanceledDueToOffline = FALSE;
  5224. BOOL fIsAPost = FALSE;
  5225. LPITEMIDLIST pidlFree = NULL;
  5226. //
  5227. // If we are processing a modal dialog, don't process it.
  5228. //
  5229. // NOTES: Checking _cRefCannotNavigate is supposed to be enough, but
  5230. // since we are dealing with random ActiveX objects, we'd better be
  5231. // robust. That's why we check IsWindowEnabled as well.
  5232. //
  5233. if ((S_OK ==_DisableModeless()) || !IsWindowEnabled(_bbd._hwnd))
  5234. {
  5235. TraceMsg(DM_ENABLEMODELESS, "CSB::_NavigateToPidl returning ERROR_BUSY");
  5236. hres = HRESULT_FROM_WIN32(ERROR_BUSY);
  5237. goto Done;
  5238. }
  5239. TraceMsg(DM_NAV, "ief NAV::%s %x %x",TEXT("_NavigateToPidl called"), pidl, grfHLNF);
  5240. // used to be we would pull a NULL out of the
  5241. // the TravelLog, but i dont think that happens anymore
  5242. ASSERT(pidl); // Get ZEKEL
  5243. // Sometimes we are navigated to the INTERNET shell folder
  5244. // if this is the case, we really want to goto the Start Page.
  5245. // This case only happens if you select "Internet Explorer" from the
  5246. // Folder Explorer Band.
  5247. if (IsBrowserFrameOptionsPidlSet(pidl, BFO_SUBSTITUE_INTERNET_START_PAGE))
  5248. {
  5249. hres = _ReplaceWithGoHome(&pidl, &pidlFree);
  5250. if (FAILED(hres))
  5251. goto Done;
  5252. }
  5253. // We should only fire the BeforeNavigate event
  5254. // if the document is not going to fire it.
  5255. // We know that the document will fire it if
  5256. // the document didn't call Navigate, the document
  5257. // knows how to navigate and the document isn't hyperlinking.
  5258. //
  5259. if (!(_dwDocFlags & DOCFLAG_NAVIGATEFROMDOC))
  5260. {
  5261. hres = _FireBeforeNavigateEvent(pidl, &fIsAPost);
  5262. if (hres == E_ABORT)
  5263. goto Done; // event handler told us to cancel
  5264. }
  5265. // if we can't go here (?), cancel the navigation
  5266. hres = _CheckZoneCrossing(pidl);
  5267. if (hres != S_OK)
  5268. goto Done;
  5269. TraceMsg(DM_NAV, "ief NAV::%s %x %x",TEXT("_CreateNewShellViewPidl called"), pidl, grfHLNF);
  5270. //
  5271. // Now that we are actually navigating...
  5272. //
  5273. // tell the frame to cancel the current navigation
  5274. // and tell it about history navigate options as it will not be getting it
  5275. // from subsequent call to Navigate
  5276. //
  5277. if (_bbd._phlf)
  5278. {
  5279. _bbd._phlf->Navigate(grfHLNF&(SHHLNF_WRITENOHISTORY|SHHLNF_NOAUTOSELECT), NULL, NULL, NULL);
  5280. }
  5281. hres = _CheckInCacheIfOffline(pidl, fIsAPost);
  5282. if (hres != S_OK)
  5283. {
  5284. fCanceledDueToOffline = TRUE;
  5285. goto Done;
  5286. }
  5287. //
  5288. // if we goto the current page, we still do a full navigate
  5289. // but we dont want to create a new entry.
  5290. //
  5291. // **EXCEPTIONS**
  5292. // if this was a generated page, ie Trident did doc.writes(),
  5293. // we need to always create a travel entry, because trident
  5294. // can rename the pidl, but it wont actually be that page.
  5295. //
  5296. // if this was a post then we need to create a travelentry.
  5297. // however if it was a travel back/fore, it will already have
  5298. // set the the bit, so we still wont create a new entry.
  5299. //
  5300. //
  5301. // NOTE: this is similar to a refresh, in that it reparses
  5302. // the entire page, but creates no travel entry.
  5303. //
  5304. if ( !_fDontAddTravelEntry // If the flag is already set, short circuit the rest
  5305. && !fIsAPost // ...and not a Post
  5306. && !_fGeneratedPage // ...and not a Generated Page
  5307. && !(grfHLNF & HLNF_CREATENOHISTORY) // ...and the CREATENOHISTORY flag is NOT set
  5308. && pidl // ...and we have a pidl to navigate to
  5309. && _bbd._pidlCur // ...as well as a current pidl
  5310. && ILIsEqual(pidl, _bbd._pidlCur) // ...and the pidls are equal
  5311. )
  5312. _fDontAddTravelEntry = TRUE; // Then set the DontAddTravelEntry flag.
  5313. TraceMsg(TF_TRAVELLOG, "CBB:_NavToPidl() _fDontAddTravelEntry = %d", _fDontAddTravelEntry);
  5314. _fGeneratedPage = FALSE;
  5315. hres = _CreateNewShellViewPidl(pidl, grfHLNF, fSBSP);
  5316. _dwDocFlags &= ~(DOCFLAG_NAVIGATEFROMDOC | DOCFLAG_SETNAVIGATABLECODEPAGE);
  5317. if (SUCCEEDED(hres))
  5318. {
  5319. ATOMICRELEASE(_pHTMLDocument);
  5320. }
  5321. Done:
  5322. if (FAILED(hres))
  5323. {
  5324. TraceMsg(DM_WARNING, "CSB::_NavigateToPidl _CreateNewShellViewPidl failed %x", hres);
  5325. // On failure we won't hit _ActivatePendingView
  5326. OnReadyStateChange(NULL, READYSTATE_COMPLETE);
  5327. // if this was navigation via ITravelLog,
  5328. // this will revert us to the original position
  5329. if (_fDontAddTravelEntry)
  5330. {
  5331. ITravelLog *ptl;
  5332. if(SUCCEEDED(GetTravelLog(&ptl)))
  5333. {
  5334. ptl->Revert();
  5335. ptl->Release();
  5336. }
  5337. _fDontAddTravelEntry = FALSE;
  5338. ASSERT(!_fIsLocalAnchor);
  5339. ATOMICRELEASE(_poleHistory);
  5340. ATOMICRELEASE(_pbcHistory);
  5341. ATOMICRELEASE(_pstmHistory);
  5342. }
  5343. if (_pbsOuter)
  5344. _pbsOuter->UpdateBackForwardState();
  5345. // we failed and have nothing to show for it...
  5346. if (!_bbd._pidlCur && !_fNavigatedToBlank)
  5347. {
  5348. TCHAR szResURL[MAX_URL_STRING];
  5349. if (fCanceledDueToOffline)
  5350. {
  5351. hres = MLBuildResURLWrap(TEXT("shdoclc.dll"),
  5352. HINST_THISDLL,
  5353. ML_CROSSCODEPAGE,
  5354. TEXT("offcancl.htm"),
  5355. szResURL,
  5356. ARRAYSIZE(szResURL),
  5357. TEXT("shdocvw.dll"));
  5358. if (SUCCEEDED(hres))
  5359. {
  5360. _ShowBlankPage(szResURL, pidl);
  5361. }
  5362. }
  5363. else
  5364. {
  5365. // NT #274562: We only want to navigate to the
  5366. // about:NavigationCancelled page if it wasn't
  5367. // a navigation to file path. (UNC or Drive).
  5368. // The main reason for this is that if the user
  5369. // enters "\\unc\share" into Start->Run and
  5370. // the window can't successfully navigate to the
  5371. // share because permissions don't allow it, we
  5372. // want to close the window after the user hits
  5373. // [Cancel] in the [Retry][Cancel] dialog. This
  5374. // is to prevent the shell from appearing to have
  5375. // shell integrated bugs and to be compatible with
  5376. // the old shell.
  5377. if ( IsBrowserFrameOptionsPidlSet(_bbd._pidlCur, BFO_SHOW_NAVIGATION_CANCELLED ) )
  5378. {
  5379. hres = MLBuildResURLWrap(TEXT("shdoclc.dll"),
  5380. HINST_THISDLL,
  5381. ML_CROSSCODEPAGE,
  5382. TEXT("navcancl.htm"),
  5383. szResURL,
  5384. ARRAYSIZE(szResURL),
  5385. TEXT("shdocvw.dll"));
  5386. if (SUCCEEDED(hres))
  5387. {
  5388. _ShowBlankPage(szResURL, pidl);
  5389. }
  5390. }
  5391. }
  5392. }
  5393. }
  5394. ILFree(pidlFree);
  5395. return hres;
  5396. }
  5397. HRESULT CBaseBrowser2::OnReadyStateChange(IShellView* psvSource, DWORD dwReadyState)
  5398. {
  5399. BOOL fChange = FALSE;
  5400. if (psvSource)
  5401. {
  5402. if (IsSameObject(psvSource, _bbd._psv))
  5403. {
  5404. TraceMsg(TF_SHDNAVIGATE, "basesb(%x)::OnReadyStateChange(Current, %d)", this, dwReadyState);
  5405. fChange = (_dwReadyStateCur != dwReadyState);
  5406. _dwReadyStateCur = dwReadyState;
  5407. if ((READYSTATE_COMPLETE == dwReadyState) && !_fReleasingShellView)
  5408. _Exec_psbMixedZone();
  5409. }
  5410. else if (IsSameObject(psvSource, _bbd._psvPending))
  5411. {
  5412. TraceMsg(TF_SHDNAVIGATE, "basesb(%x)::OnReadyStateChange(Pending, %d)", this, dwReadyState);
  5413. fChange = (_dwReadyStatePending != dwReadyState);
  5414. _dwReadyStatePending = dwReadyState;
  5415. }
  5416. else if (!_bbd._psvPending)
  5417. {
  5418. // Assume psvSource != _bbd._psv && NULL==_bbd._psvPending
  5419. // means that _SwitchActivationNow is in the middle
  5420. // of _MayPlayTransition's message loop and the
  5421. // _bbd._psvPending dude is updating us.
  5422. //
  5423. // NOTE: We don't fire the event because get_ReadyState
  5424. // can't figure this out. We know we will eventually
  5425. // fire the event because CBaseBrowser2 will go to _COMPLETE
  5426. // after _SwitchActivationNow.
  5427. //
  5428. TraceMsg(TF_SHDNAVIGATE, "basesb(%x)::OnReadyStateChange(ASSUMED Pending, %d)", this, dwReadyState);
  5429. _dwReadyStatePending = dwReadyState;
  5430. }
  5431. }
  5432. else
  5433. {
  5434. // We use this function when our own simulated
  5435. // ReadyState changes
  5436. //
  5437. TraceMsg(TF_SHDNAVIGATE, "basesb(%x)::OnReadyStateChange(Self, %d)", this, dwReadyState);
  5438. fChange = (_dwReadyState != dwReadyState);
  5439. _dwReadyState = dwReadyState;
  5440. }
  5441. // No sense in firing events if nothing actually changed...
  5442. //
  5443. if (fChange && _bbd._pautoEDS)
  5444. {
  5445. DWORD dw;
  5446. IUnknown_CPContainerOnChanged(_pauto, DISPID_READYSTATE);
  5447. // if we at Complete, fire the event
  5448. get_ReadyState(&dw);
  5449. if (READYSTATE_COMPLETE == dw)
  5450. {
  5451. if ( !(_dwDocFlags & DOCFLAG_DOCCANNAVIGATE)
  5452. || !_bbd._fIsViewMSHTML)
  5453. {
  5454. FireEvent_DocumentComplete(_bbd._pautoEDS, _bbd._pautoWB2, _bbd._pidlCur);
  5455. }
  5456. // If we hit this, we have not picked up the history object we created.
  5457. //
  5458. AssertMsg(_fDontAddTravelEntry || !_poleHistory, TEXT("CBB::OnDocComplete: nobody picked up _poleHistory"));
  5459. if (g_dwProfileCAP & 0x00080000)
  5460. {
  5461. StopCAP();
  5462. }
  5463. ATOMICRELEASE(_pphHistory);
  5464. }
  5465. }
  5466. return S_OK;
  5467. }
  5468. HRESULT CBaseBrowser2::get_ReadyState(DWORD * pdwReadyState)
  5469. {
  5470. DWORD dw = _dwReadyState;
  5471. if (_bbd._psvPending && _dwReadyStatePending < dw)
  5472. {
  5473. dw = _dwReadyStatePending;
  5474. }
  5475. if (_bbd._psv && _dwReadyStateCur < dw)
  5476. {
  5477. dw = _dwReadyStateCur;
  5478. }
  5479. *pdwReadyState = dw;
  5480. return S_OK;
  5481. }
  5482. HRESULT CBaseBrowser2::_updateNavigationUI()
  5483. {
  5484. if (_fNavigate || _fDescendentNavigate)
  5485. {
  5486. SetCursor(LoadCursor(NULL, IDC_APPSTARTING));
  5487. if (!_fDownloadSet)
  5488. {
  5489. FireEvent_DoInvokeDispid(_bbd._pautoEDS, DISPID_DOWNLOADBEGIN);
  5490. _fDownloadSet = TRUE;
  5491. }
  5492. }
  5493. else
  5494. {
  5495. if (_fDownloadSet)
  5496. {
  5497. FireEvent_DoInvokeDispid(_bbd._pautoEDS, DISPID_DOWNLOADCOMPLETE);
  5498. _fDownloadSet = FALSE;
  5499. }
  5500. SetCursor(LoadCursor(NULL, IDC_ARROW));
  5501. }
  5502. return S_OK;
  5503. }
  5504. HRESULT CBaseBrowser2::SetNavigateState(BNSTATE bnstate)
  5505. {
  5506. switch (bnstate)
  5507. {
  5508. case BNS_BEGIN_NAVIGATE:
  5509. case BNS_NAVIGATE:
  5510. _fNavigate = TRUE;
  5511. _updateNavigationUI();
  5512. break;
  5513. case BNS_NORMAL:
  5514. _fNavigate = FALSE;
  5515. _updateNavigationUI();
  5516. break;
  5517. }
  5518. return S_OK;
  5519. }
  5520. HRESULT CBaseBrowser2::GetNavigateState(BNSTATE *pbnstate)
  5521. {
  5522. // Return Navigate if we are processing a navigation or if
  5523. // we are processing a modal dialog.
  5524. //
  5525. // NOTES: Checking _cRefCannotNavigate is supposed to be enough, but
  5526. // since we are dealing with random ActiveX objects, we'd better be
  5527. // robust. That's why we check IsWindowEnabled as well.
  5528. //
  5529. *pbnstate = (_fNavigate || (S_OK ==_DisableModeless()) || _fDescendentNavigate ||
  5530. !IsWindowEnabled(_bbd._hwnd)) ? BNS_NAVIGATE : BNS_NORMAL;
  5531. return S_OK;
  5532. }
  5533. HRESULT CBaseBrowser2::UpdateBackForwardState(void)
  5534. {
  5535. if (_fTopBrowser)
  5536. {
  5537. _UpdateBackForwardState();
  5538. }
  5539. else
  5540. {
  5541. // sigh, BrowserBand now makes this fire
  5542. //ASSERT(_fTopBrowser);
  5543. IBrowserService *pbs = NULL;
  5544. TraceMsg(TF_SHDNAVIGATE, "cbb.ohlfn: !_fTopBrowser (BrowserBand?)");
  5545. if (SUCCEEDED(_pspOuter->QueryService(SID_STopFrameBrowser, IID_PPV_ARG(IBrowserService, &pbs))))
  5546. {
  5547. BOOL fTopFrameBrowser = IsSameObject(pbs, SAFECAST(this, IShellBrowser *));
  5548. if (!fTopFrameBrowser)
  5549. pbs->UpdateBackForwardState();
  5550. else
  5551. _UpdateBackForwardState();
  5552. pbs->Release();
  5553. }
  5554. }
  5555. return S_OK;
  5556. }
  5557. HRESULT CBaseBrowser2::QueryService(REFGUID guidService, REFIID riid, void **ppv)
  5558. {
  5559. HRESULT hr;
  5560. *ppv = NULL;
  5561. //
  5562. // NOTES: Notice that CBaseBrowser2 directly expose the automation
  5563. // service object via QueryService. CWebBrowserSB will appropriately
  5564. // dispatch those. See comments on CWebBrowserSB::QueryService for
  5565. // detail. (SatoNa)
  5566. //
  5567. if (IsEqualGUID(guidService, SID_SWebBrowserApp) ||
  5568. IsEqualGUID(guidService, SID_SContainerDispatch) ||
  5569. IsEqualGUID(guidService, IID_IExpDispSupport))
  5570. {
  5571. hr = _bbd._pautoSS->QueryInterface(riid, ppv);
  5572. }
  5573. else if (IsEqualGUID(guidService, SID_SHlinkFrame) ||
  5574. IsEqualGUID(guidService, IID_ITargetFrame2) ||
  5575. IsEqualGUID(guidService, IID_ITargetFrame))
  5576. {
  5577. hr = _ptfrm->QueryInterface(riid, ppv);
  5578. }
  5579. else if (IsEqualGUID(guidService, SID_STopLevelBrowser) ||
  5580. IsEqualGUID(guidService, SID_STopFrameBrowser) ||
  5581. IsEqualGUID(guidService, SID_STopWindow) ||
  5582. IsEqualGUID(guidService, SID_SProfferService))
  5583. {
  5584. if (IsEqualGUID(riid, IID_IUrlHistoryStg))
  5585. {
  5586. ASSERT(_fTopBrowser);
  5587. if (!_pIUrlHistoryStg)
  5588. {
  5589. // create this object the first time it's asked for
  5590. CoCreateInstance(CLSID_CUrlHistory, NULL, CLSCTX_INPROC_SERVER,
  5591. IID_PPV_ARG(IUrlHistoryStg, &_pIUrlHistoryStg));
  5592. }
  5593. if (_pIUrlHistoryStg)
  5594. hr = _pIUrlHistoryStg->QueryInterface(riid, ppv);
  5595. else
  5596. hr = E_NOINTERFACE;
  5597. }
  5598. else if (IsEqualGUID(riid, IID_IToolbarExt))
  5599. {
  5600. // This code should all migrate to a helper object after IE5B2. So this
  5601. // should be temporary (stevepro).
  5602. if (!_pToolbarExt)
  5603. {
  5604. IUnknown* punk;
  5605. if (SUCCEEDED(CBrowserExtension_CreateInstance(NULL, &punk, NULL)))
  5606. {
  5607. IUnknown_SetSite(punk, _psbOuter);
  5608. punk->QueryInterface(IID_PPV_ARG(IToolbarExt, &_pToolbarExt));
  5609. punk->Release();
  5610. }
  5611. }
  5612. if (_pToolbarExt)
  5613. hr = _pToolbarExt->QueryInterface(riid, ppv);
  5614. else
  5615. hr = E_NOINTERFACE;
  5616. }
  5617. else
  5618. hr = QueryInterface(riid, ppv);
  5619. }
  5620. else if (IsEqualGUID(guidService, SID_SUrlHistory))
  5621. {
  5622. if (!_pIUrlHistoryStg)
  5623. {
  5624. // Asking for it creates a copy in _pIUrlHistoryStg
  5625. IUrlHistoryStg *puhs;
  5626. if (SUCCEEDED(_pspOuter->QueryService(SID_STopLevelBrowser, IID_PPV_ARG(IUrlHistoryStg, &puhs))))
  5627. {
  5628. if (!_pIUrlHistoryStg)
  5629. _pIUrlHistoryStg = puhs;
  5630. else
  5631. puhs->Release();
  5632. }
  5633. }
  5634. if (_pIUrlHistoryStg)
  5635. hr = _pIUrlHistoryStg->QueryInterface(riid, ppv);
  5636. else
  5637. hr = E_NOINTERFACE;
  5638. }
  5639. else if (IsEqualGUID(guidService, SID_SShellBrowser) ||
  5640. IsEqualGUID(guidService, SID_SVersionHost))
  5641. {
  5642. if (IsEqualIID(riid, IID_IHlinkFrame))
  5643. {
  5644. // HACK: MSHTML uses IID_IShellBrowser instead of SID_SHlinkFrame
  5645. hr = _pspOuter->QueryService(SID_SHlinkFrame, riid, ppv);
  5646. }
  5647. else if (IsEqualIID(riid, IID_IBindCtx) && _bbd._phlf)
  5648. {
  5649. // HACK ALERT: Notice that we are using QueryService to the
  5650. // other direction here. We must make it absolutely sure
  5651. // that we'll never infinitly QueryService each other.
  5652. hr = IUnknown_QueryService(_bbd._phlf, IID_IHlinkFrame, riid, ppv);
  5653. }
  5654. else
  5655. {
  5656. hr = QueryInterface(riid, ppv);
  5657. }
  5658. }
  5659. else if (IsEqualGUID(guidService, SID_SOmWindow))
  5660. {
  5661. // HACK ALERT: Notice that we are using QueryService to the
  5662. // other direction here. We must make it absolutely sure
  5663. // that we'll never infinitly QueryService each other.
  5664. hr = IUnknown_QueryService(_ptfrm, SID_SOmWindow, riid, ppv);
  5665. }
  5666. else if (IsEqualGUID(guidService, IID_IElementNamespaceTable) && _bbd._psv)
  5667. {
  5668. hr = IUnknown_QueryService(_bbd._psv, IID_IElementNamespaceTable, riid, ppv);
  5669. }
  5670. else if (IsEqualGUID(guidService, SID_STravelLogCursor))
  5671. {
  5672. // exposed travel log object
  5673. if (!_pITravelLogStg)
  5674. {
  5675. // create this object the first time it's asked for
  5676. ITravelLog * ptl;
  5677. GetTravelLog(&ptl);
  5678. ITravelLogEx *ptlx;
  5679. if (ptl && SUCCEEDED(ptl->QueryInterface(IID_PPV_ARG(ITravelLogEx, &ptlx))))
  5680. {
  5681. hr = CreatePublicTravelLog(SAFECAST(this, IBrowserService *), ptlx, &_pITravelLogStg);
  5682. ptlx->Release();
  5683. }
  5684. SAFERELEASE(ptl);
  5685. }
  5686. if (_pITravelLogStg)
  5687. {
  5688. hr = _pITravelLogStg->QueryInterface(riid, ppv);
  5689. }
  5690. }
  5691. else if (IsEqualGUID(riid,IID_IEnumPrivacyRecords))
  5692. {
  5693. IHTMLWindow2 * pIW = NULL;
  5694. IServiceProvider * pISP = NULL;
  5695. hr = QueryService(IID_IHTMLWindow2, IID_PPV_ARG(IHTMLWindow2, &pIW));
  5696. if (SUCCEEDED(hr))
  5697. {
  5698. hr = pIW->QueryInterface(IID_PPV_ARG(IServiceProvider, &pISP));
  5699. if (SUCCEEDED(hr))
  5700. {
  5701. hr = pISP->QueryService(IID_IEnumPrivacyRecords, IID_IEnumPrivacyRecords, ppv);
  5702. pISP->Release();
  5703. }
  5704. pIW->Release();
  5705. }
  5706. }
  5707. else
  5708. {
  5709. hr = IProfferServiceImpl::QueryService(guidService, riid, ppv);
  5710. }
  5711. ASSERT(SUCCEEDED(hr) ? *ppv != NULL : *ppv == NULL); // COM rules
  5712. return hr;
  5713. }
  5714. void CBaseBrowser2::OnDataChange(FORMATETC *, STGMEDIUM *)
  5715. {
  5716. }
  5717. void CBaseBrowser2::OnViewChange(DWORD dwAspect, LONG lindex)
  5718. {
  5719. _ViewChange(dwAspect, lindex);
  5720. }
  5721. void CBaseBrowser2::OnRename(IMoniker *)
  5722. {
  5723. }
  5724. void CBaseBrowser2::OnSave()
  5725. {
  5726. }
  5727. void CBaseBrowser2::OnClose()
  5728. {
  5729. _ViewChange(DVASPECT_CONTENT, -1);
  5730. }
  5731. // *** IDropTarget ***
  5732. // These methods are defined in shdocvw.cpp
  5733. extern DWORD CommonDragEnter(IDataObject *pdtobj, DWORD grfKeyState, POINTL pt);
  5734. // Use the ShellView IDropTarget functions whenever they are implemented
  5735. // IDropTarget::DragEnter
  5736. HRESULT CBaseBrowser2::DragEnter(IDataObject *pdtobj, DWORD grfKeyState, POINTL ptl, DWORD *pdwEffect)
  5737. {
  5738. if (_pdtView)
  5739. return _pdtView->DragEnter(pdtobj, grfKeyState, ptl, pdwEffect);
  5740. else
  5741. {
  5742. if (_fNoDragDrop)
  5743. {
  5744. _dwDropEffect = DROPEFFECT_NONE;
  5745. }
  5746. else
  5747. {
  5748. _dwDropEffect = CommonDragEnter(pdtobj, grfKeyState, ptl);
  5749. }
  5750. *pdwEffect &= _dwDropEffect;
  5751. }
  5752. return S_OK;
  5753. }
  5754. // IDropTarget::DragOver
  5755. HRESULT CBaseBrowser2::DragOver(DWORD grfKeyState, POINTL ptl, DWORD *pdwEffect)
  5756. {
  5757. if (S_OK == _DisableModeless())
  5758. {
  5759. *pdwEffect = 0;
  5760. return S_OK;
  5761. }
  5762. if (_pdtView)
  5763. return _pdtView->DragOver(grfKeyState, ptl, pdwEffect);
  5764. *pdwEffect &= _dwDropEffect;
  5765. return S_OK;
  5766. }
  5767. // IDropTarget::DragLeave
  5768. HRESULT CBaseBrowser2::DragLeave(void)
  5769. {
  5770. if (_pdtView)
  5771. return _pdtView->DragLeave();
  5772. return S_OK;
  5773. }
  5774. // IDropTarget::DragDrop
  5775. HRESULT CBaseBrowser2::Drop(IDataObject *pdtobj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
  5776. {
  5777. if (S_OK == _DisableModeless())
  5778. {
  5779. *pdwEffect = 0;
  5780. return S_OK;
  5781. }
  5782. BOOL fNavigateDone = FALSE;
  5783. HRESULT hr = E_FAIL;
  5784. // If this is a shortcut - we want it to go via _NavIEShortcut
  5785. // First check if it indeed a shortcut
  5786. STGMEDIUM medium;
  5787. if (_ptfrm && (DataObj_GetDataOfType(pdtobj, CF_HDROP, &medium)))
  5788. {
  5789. WCHAR wszPath[MAX_PATH];
  5790. if (DragQueryFileW((HDROP)medium.hGlobal, 0, wszPath, ARRAYSIZE(wszPath)))
  5791. {
  5792. LPWSTR pwszExtension = PathFindExtensionW(wszPath);
  5793. // Check the extension to see if it is a .URL file
  5794. if (0 == StrCmpIW(pwszExtension, L".url"))
  5795. {
  5796. // It is an internet shortcut
  5797. VARIANT varShortCutPath = {0};
  5798. VARIANT varFlag = {0};
  5799. varFlag.vt = VT_BOOL;
  5800. varFlag.boolVal = VARIANT_TRUE;
  5801. LBSTR::CString strPath( wszPath );
  5802. varShortCutPath.vt = VT_BSTR;
  5803. varShortCutPath.bstrVal = strPath;
  5804. hr = IUnknown_Exec(_ptfrm, &CGID_Explorer, SBCMDID_IESHORTCUT, 0, &varShortCutPath, &varFlag);
  5805. fNavigateDone = SUCCEEDED(hr);
  5806. if(fNavigateDone)
  5807. {
  5808. DragLeave();
  5809. }
  5810. }
  5811. }
  5812. // must call ReleaseStgMediumHGLOBAL since DataObj_GetDataOfType added an extra GlobalLock
  5813. ReleaseStgMediumHGLOBAL(NULL, &medium);
  5814. }
  5815. if (FALSE == fNavigateDone)
  5816. {
  5817. if (_pdtView)
  5818. {
  5819. hr = _pdtView->Drop(pdtobj, grfKeyState, pt, pdwEffect);
  5820. }
  5821. else
  5822. {
  5823. LPITEMIDLIST pidlTarget;
  5824. hr = SHPidlFromDataObject(pdtobj, &pidlTarget, NULL, 0);
  5825. if (SUCCEEDED(hr))
  5826. {
  5827. ASSERT(pidlTarget);
  5828. hr = _psbOuter->BrowseObject(pidlTarget, SBSP_SAMEBROWSER | SBSP_ABSOLUTE);
  5829. ILFree(pidlTarget);
  5830. }
  5831. }
  5832. }
  5833. return hr;
  5834. }
  5835. HRESULT CBaseBrowser2::_FireBeforeNavigateEvent(LPCITEMIDLIST pidl, BOOL* pfIsPost)
  5836. {
  5837. HRESULT hres = S_OK;
  5838. IBindStatusCallback * pBindStatusCallback;
  5839. LPTSTR pszHeaders = NULL;
  5840. LPBYTE pPostData = NULL;
  5841. DWORD cbPostData = 0;
  5842. BOOL fCancelled=FALSE;
  5843. STGMEDIUM stgPostData;
  5844. BOOL fHavePostStg = FALSE;
  5845. *pfIsPost = FALSE;
  5846. // If this is the first BeforeNavigateEvent of a ViewLinkedWebOC we do not need to fire.
  5847. // It is fired by the hosting Trident. Note that _fIsViewLinkedWebOC is only set by the
  5848. // host, so we need not worry about BeforeNavigateEvent not being fired for other in other
  5849. // instances of the WebOC.
  5850. if (_fIsViewLinkedWebOC && (!_fHadFirstBeforeNavigate))
  5851. {
  5852. _fHadFirstBeforeNavigate = TRUE;
  5853. return hres;
  5854. }
  5855. // get the bind status callback for this browser and ask it for
  5856. // headers and post data
  5857. if (SUCCEEDED(GetTopLevelPendingBindStatusCallback(this,&pBindStatusCallback)))
  5858. {
  5859. GetHeadersAndPostData(pBindStatusCallback,&pszHeaders,&stgPostData,&cbPostData, pfIsPost);
  5860. pBindStatusCallback->Release();
  5861. fHavePostStg = TRUE;
  5862. if (stgPostData.tymed == TYMED_HGLOBAL)
  5863. {
  5864. pPostData = (LPBYTE) stgPostData.hGlobal;
  5865. }
  5866. }
  5867. // Fire a BeforeNavigate event to inform container that we are about
  5868. // to navigate and to give it a chance to cancel. We have to ask
  5869. // for post data and headers to pass to event, so only do this if someone
  5870. // is actually hooked up to the event (HasSinks() is TRUE).
  5871. //if (_bbd._pautoEDS->HasSinks())
  5872. {
  5873. TCHAR szFrameName[MAX_URL_STRING];
  5874. SHSTR strHeaders;
  5875. szFrameName[0] = 0;
  5876. // get our frame name
  5877. ITargetFrame2 *pOurTargetFrame;
  5878. hres = TargetQueryService(SAFECAST(this, IShellBrowser *), IID_PPV_ARG(ITargetFrame2, &pOurTargetFrame));
  5879. if (SUCCEEDED(hres))
  5880. {
  5881. LPOLESTR pwzFrameName = NULL;
  5882. pOurTargetFrame->GetFrameName(&pwzFrameName);
  5883. pOurTargetFrame->Release();
  5884. if (pwzFrameName)
  5885. {
  5886. SHUnicodeToTChar(pwzFrameName, szFrameName, ARRAYSIZE(szFrameName));
  5887. CoTaskMemFree(pwzFrameName);
  5888. }
  5889. }
  5890. strHeaders.SetStr(pszHeaders);
  5891. _pidlBeforeNavigateEvent = (LPITEMIDLIST) pidl; // no need to copy
  5892. // This is a work around for view linked weboc. Setting the frame name has side effects.
  5893. TCHAR * pEffectiveName;
  5894. if (_fIsViewLinkedWebOC && !szFrameName[0])
  5895. {
  5896. pEffectiveName = _szViewLinkedWebOCFrameName;
  5897. }
  5898. else
  5899. {
  5900. pEffectiveName = szFrameName[0] ? szFrameName : NULL;
  5901. }
  5902. // fire the event!
  5903. FireEvent_BeforeNavigate(_bbd._pautoEDS, _bbd._hwnd, _bbd._pautoWB2,
  5904. pidl, NULL, 0, pEffectiveName,
  5905. pPostData, cbPostData, strHeaders.GetStr(), &fCancelled);
  5906. ASSERT(_pidlBeforeNavigateEvent == pidl);
  5907. _pidlBeforeNavigateEvent = NULL;
  5908. // free anything we alloc'd above
  5909. if (pszHeaders)
  5910. {
  5911. LocalFree(pszHeaders);
  5912. pszHeaders = NULL;
  5913. }
  5914. if (fCancelled)
  5915. {
  5916. // container told us to cancel
  5917. hres = E_ABORT;
  5918. }
  5919. }
  5920. if (fHavePostStg)
  5921. {
  5922. ReleaseStgMedium(&stgPostData);
  5923. }
  5924. return hres;
  5925. }
  5926. HRESULT CBaseBrowser2::SetTopBrowser()
  5927. {
  5928. _fTopBrowser = TRUE;
  5929. #ifdef MESSAGEFILTER
  5930. if (!_lpMF)
  5931. {
  5932. /*
  5933. * Create a message filter here to pull out WM_TIMER's while we are
  5934. * busy. The animation timer, along with other timers, can get
  5935. * piled up otherwise which can fill the message queue and thus USER's
  5936. * heap.
  5937. */
  5938. _lpMF = new CMsgFilter();
  5939. if (_lpMF && !(((CMsgFilter *)_lpMF)->Initialize()))
  5940. {
  5941. ATOMICRELEASE(_lpMF);
  5942. }
  5943. }
  5944. #endif
  5945. return S_OK;
  5946. }
  5947. HRESULT CBaseBrowser2::_ResizeView()
  5948. {
  5949. _pbsOuter->_UpdateViewRectSize();
  5950. if (_pact)
  5951. {
  5952. RECT rc;
  5953. GetBorder(&rc);
  5954. TraceMsg(TF_SHDUIACTIVATE, "UIW::SetBorderSpaceDW calling _pact->ResizeBorder");
  5955. _pact->ResizeBorder(&rc, this, TRUE);
  5956. }
  5957. return S_OK;
  5958. }
  5959. HRESULT CBaseBrowser2::_ResizeNextBorder(UINT itb)
  5960. {
  5961. // (derived class resizes inner toolbar if any)
  5962. return _ResizeView();
  5963. }
  5964. HRESULT CBaseBrowser2::_OnFocusChange(UINT itb)
  5965. {
  5966. #if 0
  5967. // the OC *does* get here (it's not aggregated so _pbsOuter->_OnFocusChange
  5968. // ends up here not in commonsb). not sure if E_NOTIMPL is o.k., but
  5969. // for now it's what we'll do...
  5970. ASSERT(0);
  5971. #endif
  5972. return E_NOTIMPL;
  5973. }
  5974. HRESULT CBaseBrowser2::OnFocusChangeIS(IUnknown* punkSrc, BOOL fSetFocus)
  5975. {
  5976. ASSERT(0); // split: untested!
  5977. // do we need to do _UIActivateView?
  5978. ASSERT(fSetFocus); // i think?
  5979. return E_NOTIMPL;
  5980. }
  5981. HRESULT CBaseBrowser2::v_ShowHideChildWindows(BOOL fChildOnly)
  5982. {
  5983. // (derived class does ShowDW on all toolbars)
  5984. if (!fChildOnly)
  5985. {
  5986. _pbsOuter->_ResizeNextBorder(0);
  5987. // This is called in ResizeNextBorder
  5988. // _UpdateViewRectSize();
  5989. }
  5990. return S_OK;
  5991. }
  5992. //*** _ExecChildren -- broadcast Exec to view and toolbars
  5993. // NOTES
  5994. // we might do *both* punkBar and fBroadcast if we want to send stuff
  5995. // to both the view and to all toolbars, e.g. 'stop' or 'refresh'.
  5996. //
  5997. // Note: n.b. the tray isn't a real toolbar, so it won't get called (sigh...).
  5998. HRESULT CBaseBrowser2::_ExecChildren(IUnknown *punkBar, BOOL fBroadcast, const GUID *pguidCmdGroup,
  5999. DWORD nCmdID, DWORD nCmdexecopt,
  6000. VARIANTARG *pvarargIn, VARIANTARG *pvarargOut)
  6001. {
  6002. //ASSERT(!fBroadcast); // only derived class supports this
  6003. // alanau: but CWebBrowserSB doesn't override this method, so we hit this assert.
  6004. // 1st, send to specified guy (if requested)
  6005. if (punkBar != NULL)
  6006. {
  6007. // send to specified guy
  6008. IUnknown_Exec(punkBar, pguidCmdGroup, nCmdID, nCmdexecopt, pvarargIn, pvarargOut);
  6009. }
  6010. // (derived class broadcasts to toolbars)
  6011. return S_OK;
  6012. }
  6013. HRESULT CBaseBrowser2::_SendChildren(HWND hwndBar, BOOL fBroadcast, UINT uMsg, WPARAM wParam, LPARAM lParam)
  6014. {
  6015. #if 0
  6016. // the OC *does* get here (it's not aggregated so _pbsOuter->_SendChildren
  6017. // ends up here not in commonsb). since there are no kids i guess it's
  6018. // ok to just drop the fBroadcast on the floor.
  6019. ASSERT(!fBroadcast); // only derived class supports this
  6020. #endif
  6021. // 1st, send to specified guy (if requested)
  6022. if (hwndBar != NULL)
  6023. {
  6024. // send to specified guy
  6025. SendMessage(hwndBar, uMsg, wParam, lParam);
  6026. }
  6027. // (derived class broadcasts to toolbars)
  6028. return S_OK;
  6029. }
  6030. //
  6031. // Handle <META HTTP-EQUIV ...> headers for lower components
  6032. //
  6033. HRESULT CBaseBrowser2::OnHttpEquiv(IShellView* psv, BOOL fDone, VARIANT *pvarargIn, VARIANT *pvarargOut)
  6034. {
  6035. return OLECMDERR_E_NOTSUPPORTED;
  6036. } // _HandleHttpEquiv
  6037. STDMETHODIMP CBaseBrowser2::GetPalette( HPALETTE * phpal )
  6038. {
  6039. BOOL fRes = FALSE;
  6040. if ( _hpalBrowser )
  6041. {
  6042. *phpal = _hpalBrowser;
  6043. fRes = TRUE;
  6044. }
  6045. return fRes ? NOERROR : E_FAIL;
  6046. }
  6047. //
  6048. // IPersist
  6049. //
  6050. HRESULT
  6051. CBaseBrowser2::GetClassID(CLSID *pclsid)
  6052. {
  6053. return E_NOTIMPL;
  6054. }
  6055. //
  6056. // IPersistHistory
  6057. //
  6058. #ifdef DEBUG
  6059. #define c_szFrameMagic TEXT("IE4ViewStream")
  6060. #define c_cchFrameMagic SIZECHARS(c_szFrameMagic)
  6061. #endif
  6062. // NOTE this is almost the same kind of data that is
  6063. // stored in a TravelEntry.
  6064. typedef struct _PersistedFrame {
  6065. DWORD cbSize;
  6066. DWORD type;
  6067. DWORD lock;
  6068. DWORD bid;
  6069. CLSID clsid;
  6070. DWORD cbPidl;
  6071. } PERSISTEDFRAME, *PPERSISTEDFRAME;
  6072. #define PFTYPE_USEPIDL 1
  6073. #define PFTYPE_USECLSID 2
  6074. #define PFFLAG_SECURELOCK 0x00000001
  6075. HRESULT GetPersistedFrame(IStream *pstm, PPERSISTEDFRAME ppf, LPITEMIDLIST *ppidl)
  6076. {
  6077. HRESULT hr;
  6078. ASSERT(pstm);
  6079. ASSERT(ppf);
  6080. ASSERT(ppidl);
  6081. #ifdef DEBUG
  6082. TCHAR szMagic[SIZECHARS(c_szFrameMagic)];
  6083. DWORD cbMagic = CbFromCch(c_cchFrameMagic);
  6084. ASSERT(SUCCEEDED(IStream_Read(pstm, (void *) szMagic, cbMagic)));
  6085. ASSERT(!StrCmp(szMagic, c_szFrameMagic));
  6086. #endif //DEBUG
  6087. // This is pointing to the stack, make sure it starts NULL
  6088. *ppidl = NULL;
  6089. if(SUCCEEDED(hr = IStream_Read(pstm, (void *) ppf, SIZEOF(PERSISTEDFRAME))))
  6090. {
  6091. if(ppf->cbSize == SIZEOF(PERSISTEDFRAME) && (ppf->type == PFTYPE_USECLSID || ppf->type == PFTYPE_USEPIDL))
  6092. {
  6093. // i used SHAlloc() cuz its what all the IL functions use
  6094. if(ppf->cbPidl)
  6095. *ppidl = (LPITEMIDLIST) SHAlloc(ppf->cbPidl);
  6096. if(*ppidl)
  6097. {
  6098. hr = IStream_Read(pstm, (void *) *ppidl, ppf->cbPidl);
  6099. if(FAILED(hr))
  6100. {
  6101. ILFree(*ppidl);
  6102. *ppidl = NULL;
  6103. }
  6104. }
  6105. else
  6106. hr = E_OUTOFMEMORY;
  6107. }
  6108. else
  6109. hr = E_UNEXPECTED;
  6110. }
  6111. return hr;
  6112. }
  6113. HRESULT
  6114. CBaseBrowser2::LoadHistory(IStream *pstm, IBindCtx *pbc)
  6115. {
  6116. HRESULT hr = E_INVALIDARG;
  6117. ASSERT(pstm);
  6118. TraceMsg(TF_TRAVELLOG, "CBB::LoadHistory entered pstm = %X, pbc = %d", pstm, pbc);
  6119. ATOMICRELEASE(_poleHistory);
  6120. ATOMICRELEASE(_pstmHistory);
  6121. ATOMICRELEASE(_pbcHistory);
  6122. if (pstm)
  6123. {
  6124. PERSISTEDFRAME pf;
  6125. LPITEMIDLIST pidl;
  6126. hr = GetPersistedFrame(pstm, &pf, &pidl);
  6127. if (SUCCEEDED(hr))
  6128. {
  6129. // need to restore the previous bid
  6130. // if this is a new window
  6131. ASSERT(pf.bid == _dwBrowserIndex || !_bbd._pidlCur);
  6132. _dwBrowserIndex = pf.bid;
  6133. _eSecureLockIconPending = pf.lock;
  6134. if (pf.type == PFTYPE_USECLSID)
  6135. {
  6136. hr = E_FAIL;
  6137. if (_pHTMLDocument)
  6138. {
  6139. if ( (_dwDocFlags & DOCFLAG_DOCCANNAVIGATE)
  6140. && IsEqualCLSID(pf.clsid, CLSID_HTMLDocument))
  6141. {
  6142. IPersistHistory * pph;
  6143. hr = _pHTMLDocument->QueryInterface(IID_PPV_ARG(IPersistHistory, &pph));
  6144. if (SUCCEEDED(hr))
  6145. {
  6146. _fDontAddTravelEntry = TRUE;
  6147. hr = pph->LoadHistory(pstm, pbc);
  6148. TraceMsg(TF_TRAVELLOG, "CBB::LoadHistory called pole->LoadHistory, hr =%X", hr);
  6149. pph->Release();
  6150. return hr;
  6151. }
  6152. }
  6153. else
  6154. {
  6155. ATOMICRELEASE(_pHTMLDocument); // We are going to cocreate a new document.
  6156. }
  6157. }
  6158. if (S_OK != hr)
  6159. {
  6160. // Get the class and instantiate
  6161. hr = CoCreateInstance(pf.clsid, NULL, CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER, IID_PPV_ARG(IOleObject, &_poleHistory));
  6162. }
  6163. if (SUCCEEDED(hr))
  6164. {
  6165. DWORD dwFlags;
  6166. hr = _poleHistory->GetMiscStatus(DVASPECT_CONTENT, &dwFlags);
  6167. if (SUCCEEDED(hr))
  6168. {
  6169. if (dwFlags & OLEMISC_SETCLIENTSITEFIRST)
  6170. {
  6171. pstm->AddRef();
  6172. if (pbc)
  6173. pbc->AddRef();
  6174. // we need to addref because we will use it async
  6175. // whoever uses it needs to release.
  6176. _pstmHistory = pstm;
  6177. _pbcHistory = pbc;
  6178. }
  6179. else
  6180. {
  6181. IPersistHistory * pph;
  6182. hr = _poleHistory->QueryInterface(IID_PPV_ARG(IPersistHistory, &pph));
  6183. if (SUCCEEDED(hr))
  6184. {
  6185. hr = pph->LoadHistory(pstm, pbc);
  6186. TraceMsg(TF_TRAVELLOG, "CBB::LoadHistory called pole->LoadHistory, hr =%X", hr);
  6187. pph->Release();
  6188. }
  6189. }
  6190. // if we made then set the prepared history object in
  6191. // _poleHistory
  6192. if (FAILED(hr))
  6193. {
  6194. ATOMICRELEASE(_poleHistory);
  6195. ATOMICRELEASE(_pstmHistory);
  6196. ATOMICRELEASE(_pbcHistory);
  6197. }
  6198. }
  6199. }
  6200. }
  6201. //
  6202. // just browse the object
  6203. // if poleHistory is set, then when the dochost is created
  6204. // it will pick up the object and use it.
  6205. // other wise we will do a normal navigate.
  6206. //
  6207. if (pidl)
  6208. {
  6209. DEBUG_CODE(TCHAR szPath[INTERNET_MAX_URL_LENGTH + 1];)
  6210. DEBUG_CODE(SHGetNameAndFlags(pidl, SHGDN_FORPARSING, szPath, ARRAYSIZE(szPath), NULL);)
  6211. DEBUG_CODE(TraceMsg(DM_TRACE, "CBB::LoadHistory: URL - %ws", szPath);)
  6212. _fDontAddTravelEntry = TRUE;
  6213. hr = _psbOuter->BrowseObject(pidl, SBSP_SAMEBROWSER | SBSP_ABSOLUTE);
  6214. ILFree(pidl);
  6215. }
  6216. else
  6217. hr = E_OUTOFMEMORY;
  6218. }
  6219. }
  6220. TraceMsg(TF_TRAVELLOG, "CBB::LoadHistory exiting, hr =%X", hr);
  6221. _pbsOuter->UpdateBackForwardState();
  6222. return hr;
  6223. }
  6224. // Save a stream represeting the history at this point.
  6225. // Be sure to keep this and GetDummyWindowData in sync.
  6226. HRESULT
  6227. CBaseBrowser2::SaveHistory(IStream *pstm)
  6228. {
  6229. HRESULT hr = E_UNEXPECTED;
  6230. TraceMsg(TF_TRAVELLOG, "CBB::SaveHistory entering, pstm =%X", pstm);
  6231. ASSERT(pstm);
  6232. if(_bbd._pidlCur)
  6233. {
  6234. PERSISTEDFRAME pf = {0};
  6235. pf.cbSize = SIZEOF(pf);
  6236. pf.bid = GetBrowserIndex();
  6237. pf.cbPidl = ILGetSize(_bbd._pidlCur);
  6238. pf.type = PFTYPE_USEPIDL;
  6239. pf.lock = _bbd._eSecureLockIcon;
  6240. DEBUG_CODE(TCHAR szPath[INTERNET_MAX_URL_LENGTH + 1];)
  6241. DEBUG_CODE(IEGetDisplayName(_bbd._pidlCur, szPath, SHGDN_FORPARSING);)
  6242. ASSERT(SUCCEEDED(IStream_Write(pstm, (void *) c_szFrameMagic, CbFromCch(c_cchFrameMagic))));
  6243. //
  6244. // in order to use IPersistHistory we need to get the CLSID of the Ole Object
  6245. // then we need to get IPersistHistory off that object
  6246. // then we can save the PERSISTEDFRAME and the pidl and then pass
  6247. // the stream down into the objects IPersistHistory
  6248. //
  6249. // Right now we circumvent the view object for history - zekel - 18-JUL-97
  6250. // right now we just grab the DocObj from the view object, and then query
  6251. // the Doc for IPersistHistory. really what we should be doing is QI the view
  6252. // for pph, and then use it. however this requires risky work with the
  6253. // navigation stack, and thus should be postponed to IE5. looking to the future
  6254. // the view could persist all kinds of great state info
  6255. //
  6256. // but now we just get the background object. but check to make sure that it
  6257. // will be using the DocObjHost code by QI for IDocViewSite
  6258. //
  6259. // _bbd._psv can be null in subframes that have not completed navigating
  6260. // before a refresh is called
  6261. //
  6262. if (!_pphHistory && _bbd._psv)
  6263. {
  6264. hr = SafeGetItemObject(_bbd._psv, SVGIO_BACKGROUND, IID_PPV_ARG(IPersistHistory, &_pphHistory));
  6265. }
  6266. if (_pphHistory)
  6267. {
  6268. IDocViewSite *pdvs;
  6269. if (SUCCEEDED(_bbd._psv->QueryInterface(IID_PPV_ARG(IDocViewSite, &pdvs))) &&
  6270. SUCCEEDED(hr = _pphHistory->GetClassID(&(pf.clsid))))
  6271. {
  6272. pf.type = PFTYPE_USECLSID;
  6273. TraceMsg(TF_TRAVELLOG, "CBB::SaveHistory is PFTYPE_USECLSID");
  6274. }
  6275. ATOMICRELEASE(pdvs);
  6276. }
  6277. if (SUCCEEDED(hr = IStream_Write(pstm,(void *)&pf, pf.cbSize)))
  6278. hr = IStream_Write(pstm,(void *)_bbd._pidlCur, pf.cbPidl);
  6279. if (SUCCEEDED(hr) && pf.type == PFTYPE_USECLSID)
  6280. hr = _pphHistory->SaveHistory(pstm);
  6281. ATOMICRELEASE(_pphHistory);
  6282. }
  6283. TraceMsg(TF_TRAVELLOG, "CBB::SaveHistory exiting, hr =%X", hr);
  6284. return hr;
  6285. }
  6286. HRESULT CBaseBrowser2::SetPositionCookie(DWORD dwPositionCookie)
  6287. {
  6288. HRESULT hr = E_FAIL;
  6289. //
  6290. // we force the browser to update its internal location and the address bar
  6291. // this depends on the fact that setposition cookie was always
  6292. // started by a ptl->Travel(). so that the current position in the ptl
  6293. // is actually the correct URL for us to have. zekel - 22-JUL-97
  6294. //
  6295. ITravelLog *ptl;
  6296. GetTravelLog(&ptl);
  6297. if(ptl)
  6298. {
  6299. ITravelEntry *pte;
  6300. if(EVAL(SUCCEEDED(ptl->GetTravelEntry(SAFECAST(this, IShellBrowser *), 0, &pte))))
  6301. {
  6302. LPITEMIDLIST pidl;
  6303. if(SUCCEEDED(pte->GetPidl(&pidl)))
  6304. {
  6305. BOOL fUnused;
  6306. ASSERT(pidl);
  6307. if (SUCCEEDED(hr = _FireBeforeNavigateEvent(pidl, &fUnused)))
  6308. {
  6309. IPersistHistory *pph;
  6310. if(_bbd._psv && SUCCEEDED(hr = SafeGetItemObject(_bbd._psv, SVGIO_BACKGROUND, IID_PPV_ARG(IPersistHistory, &pph))))
  6311. {
  6312. ASSERT(pph);
  6313. // now that we are certain that we are going to call into
  6314. // the document, we need to update the entry right before.
  6315. // NOTE: after an update, we cannot revert if there was an
  6316. // error in the Set...
  6317. ptl->UpdateEntry(SAFECAST(this, IShellBrowser *), TRUE);
  6318. hr = pph->SetPositionCookie(dwPositionCookie);
  6319. pph->Release();
  6320. // this updates the browser to the new pidl,
  6321. // and navigates there directly if necessary.
  6322. BOOL fDidBrowse;
  6323. NotifyRedirect(_bbd._psv, pidl, &fDidBrowse);
  6324. if (!fDidBrowse)
  6325. {
  6326. // fire the event!
  6327. FireEvent_NavigateComplete(_bbd._pautoEDS, _bbd._pautoWB2, _bbd._pidlCur, _bbd._hwnd);
  6328. FireEvent_DocumentComplete(_bbd._pautoEDS, _bbd._pautoWB2, _bbd._pidlCur);
  6329. }
  6330. }
  6331. }
  6332. ILFree(pidl);
  6333. }
  6334. pte->Release();
  6335. }
  6336. ptl->Release();
  6337. }
  6338. TraceMsg(TF_TRAVELLOG, "CBB::SetPositionCookie exiting, cookie = %X, hr =%X", dwPositionCookie, hr);
  6339. return hr;
  6340. }
  6341. HRESULT CBaseBrowser2::GetPositionCookie(DWORD *pdwPositionCookie)
  6342. {
  6343. HRESULT hr = E_FAIL;
  6344. IPersistHistory *pph;
  6345. ASSERT(pdwPositionCookie);
  6346. if(pdwPositionCookie && _bbd._psv && SUCCEEDED(hr = SafeGetItemObject(_bbd._psv, SVGIO_BACKGROUND, IID_PPV_ARG(IPersistHistory, &pph))))
  6347. {
  6348. ASSERT(pph);
  6349. hr = pph->GetPositionCookie(pdwPositionCookie);
  6350. pph->Release();
  6351. }
  6352. TraceMsg(TF_TRAVELLOG, "CBB::GetPositionCookie exiting, cookie = %X, hr =%X", *pdwPositionCookie, hr);
  6353. return hr;
  6354. }
  6355. DWORD CBaseBrowser2::GetBrowserIndex()
  6356. {
  6357. // the first time we request the index, we init it.
  6358. if (!_dwBrowserIndex)
  6359. {
  6360. //
  6361. // the topframe browser all have the same browser index so
  6362. // that they can trade TravelEntries if necessary. because we now
  6363. // trade around TravelEntries, then we need to make the bids relatively
  6364. // unique. and avoid ever having a random frame be BID_TOPFRAMEBROWSER
  6365. //
  6366. if (IsTopFrameBrowser(SAFECAST(this, IServiceProvider *), SAFECAST(this, IShellBrowser *)))
  6367. _dwBrowserIndex = BID_TOPFRAMEBROWSER;
  6368. else do
  6369. {
  6370. _dwBrowserIndex = SHRandom();
  6371. } while (!_dwBrowserIndex || _dwBrowserIndex == BID_TOPFRAMEBROWSER);
  6372. // psp->Release();
  6373. TraceMsg(TF_TRAVELLOG, "CBB::GetBrowserIndex() NewFrame BID = %X", _dwBrowserIndex);
  6374. }
  6375. return _dwBrowserIndex;
  6376. }
  6377. HRESULT CBaseBrowser2::GetHistoryObject(IOleObject **ppole, IStream **ppstm, IBindCtx **ppbc)
  6378. {
  6379. ASSERT(ppole);
  6380. ASSERT(ppstm);
  6381. ASSERT(ppbc);
  6382. *ppole = _poleHistory;
  6383. *ppstm = _pstmHistory;
  6384. *ppbc = _pbcHistory;
  6385. // we dont need to release, because we are just giving away our
  6386. // reference.
  6387. _poleHistory = NULL;
  6388. _pstmHistory = NULL;
  6389. _pbcHistory = NULL;
  6390. if(*ppole)
  6391. return NOERROR;
  6392. ASSERT(!*ppstm);
  6393. return E_FAIL;
  6394. }
  6395. HRESULT CBaseBrowser2::SetHistoryObject(IOleObject *pole, BOOL fIsLocalAnchor)
  6396. {
  6397. if (!_poleHistory && !_fGeneratedPage)
  6398. {
  6399. ASSERT(pole);
  6400. // Note: _fIsLocalAnchor is ignored if (_dwDocFlags & DOCFLAG_DOCCANNAVIGATE)
  6401. // is TRUE. In that case, the document (Trident) can navigate
  6402. // itself and will take care of updating the travel log.
  6403. //
  6404. _fIsLocalAnchor = fIsLocalAnchor;
  6405. if (pole)
  6406. {
  6407. _poleHistory = pole;
  6408. _poleHistory->AddRef();
  6409. return NOERROR;
  6410. }
  6411. }
  6412. return E_FAIL;
  6413. }
  6414. HRESULT CBaseBrowser2::CacheOLEServer(IOleObject *pole)
  6415. {
  6416. TraceMsg(DM_CACHEOLESERVER, "CBB::CacheOLEServer called");
  6417. HRESULT hres;
  6418. IPersist* pps;
  6419. // ISVs want to turn off this caching because it's "incovenient"
  6420. // to have the browser hold onto their object. We can do that
  6421. // with a quick registry check here, but first let's make sure
  6422. // we don't have a real bug to fix...
  6423. hres = pole->QueryInterface(IID_PPV_ARG(IPersist, &pps));
  6424. if (FAILED(hres))
  6425. {
  6426. return hres;
  6427. }
  6428. CLSID clsid = CLSID_NULL;
  6429. hres = pps->GetClassID(&clsid);
  6430. pps->Release();
  6431. if (SUCCEEDED(hres))
  6432. {
  6433. SA_BSTRGUID str;
  6434. InitFakeBSTR(&str, clsid);
  6435. VARIANT v;
  6436. hres = _bbd._pautoWB2->GetProperty(str.wsz, &v);
  6437. if (SUCCEEDED(hres) && v.vt != VT_EMPTY)
  6438. {
  6439. // We already have it. We are fine.
  6440. TraceMsg(DM_CACHEOLESERVER, "CBB::CacheOLEServer not first time");
  6441. VariantClear(&v);
  6442. }
  6443. else
  6444. {
  6445. // We don't have it yet. Add it.
  6446. v.vt = VT_UNKNOWN;
  6447. v.punkVal = ClassHolder_Create(&clsid);
  6448. if (v.punkVal)
  6449. {
  6450. hres = _bbd._pautoWB2->PutProperty(str.wsz, v);
  6451. TraceMsg(DM_CACHEOLESERVER, "CBB::CacheOLEServer first time %x", hres);
  6452. v.punkVal->Release();
  6453. }
  6454. }
  6455. }
  6456. return hres;
  6457. }
  6458. HRESULT CBaseBrowser2::GetSetCodePage(VARIANT* pvarIn, VARIANT* pvarOut)
  6459. {
  6460. // Process the out parameter first so that the client can set and
  6461. // get the previous value in a single call.
  6462. if (pvarOut)
  6463. {
  6464. pvarOut->vt = VT_I4;
  6465. pvarOut->lVal = _cp;
  6466. }
  6467. if (pvarIn && pvarIn->vt==VT_I4)
  6468. {
  6469. TraceMsg(DM_DOCCP, "CBB::GetSetCodePage changing _cp from %d to %d", _cp, pvarIn->lVal);
  6470. _cp = pvarIn->lVal;
  6471. }
  6472. return S_OK;
  6473. }
  6474. HRESULT CBaseBrowser2::GetPidl(LPITEMIDLIST *ppidl)
  6475. {
  6476. ASSERT(ppidl);
  6477. *ppidl = ILClone(_bbd._pidlCur);
  6478. return *ppidl ? S_OK : E_FAIL;
  6479. }
  6480. HRESULT CBaseBrowser2::SetReferrer(LPITEMIDLIST pidl)
  6481. {
  6482. return E_NOTIMPL;
  6483. }
  6484. HRESULT CBaseBrowser2::GetBrowserByIndex(DWORD dwID, IUnknown **ppunk)
  6485. {
  6486. HRESULT hr = E_FAIL;
  6487. ASSERT(ppunk);
  6488. *ppunk = NULL;
  6489. //gotta get the target frame ...
  6490. ITargetFramePriv * ptf;
  6491. if(SUCCEEDED(_ptfrm->QueryInterface(IID_PPV_ARG(ITargetFramePriv, &ptf))))
  6492. {
  6493. ASSERT(ptf);
  6494. hr = ptf->FindBrowserByIndex(dwID, ppunk);
  6495. ptf->Release();
  6496. }
  6497. return hr;
  6498. }
  6499. HRESULT CBaseBrowser2::GetTravelLog(ITravelLog **pptl)
  6500. {
  6501. *pptl = NULL;
  6502. if (!_bbd._ptl)
  6503. {
  6504. IBrowserService *pbs;
  6505. if (SUCCEEDED(_pspOuter->QueryService(SID_STopFrameBrowser, IID_PPV_ARG(IBrowserService, &pbs))))
  6506. {
  6507. if (IsSameObject(SAFECAST(this, IBrowserService *), pbs))
  6508. {
  6509. // we are it, so we need to make us a TravelLog
  6510. CreateTravelLog(&_bbd._ptl);
  6511. }
  6512. else
  6513. {
  6514. pbs->GetTravelLog(&_bbd._ptl);
  6515. }
  6516. pbs->Release();
  6517. }
  6518. }
  6519. return _bbd._ptl ? _bbd._ptl->QueryInterface(IID_PPV_ARG(ITravelLog, pptl)) : E_FAIL;
  6520. }
  6521. HRESULT CBaseBrowser2::InitializeTravelLog(ITravelLog* ptl, DWORD dwBrowserIndex)
  6522. {
  6523. ptl->QueryInterface(IID_PPV_ARG(ITravelLog, &_bbd._ptl)); // hold a copy
  6524. _dwBrowserIndex = dwBrowserIndex;
  6525. return S_OK;
  6526. }
  6527. // Let the top level browser know that it might need to update it's zones information
  6528. void CBaseBrowser2::_Exec_psbMixedZone()
  6529. {
  6530. IShellBrowser *psbTop;
  6531. if (SUCCEEDED(_pspOuter->QueryService(SID_STopLevelBrowser, IID_PPV_ARG(IShellBrowser, &psbTop))))
  6532. {
  6533. IUnknown_Exec(psbTop, &CGID_Explorer, SBCMDID_MIXEDZONE, 0, NULL, NULL);
  6534. psbTop->Release();
  6535. }
  6536. }
  6537. STDMETHODIMP CBaseBrowser2::QueryUseLocalVersionVector(BOOL *pfUseLocal)
  6538. {
  6539. *pfUseLocal = FALSE;
  6540. return S_OK;
  6541. }
  6542. STDMETHODIMP CBaseBrowser2::QueryVersionVector(IVersionVector *pVersion)
  6543. {
  6544. HRESULT hr;
  6545. ULONG cchVer = 0;
  6546. // Was IE's version set by a registry entry?
  6547. // This simplified call checks for presence of the IE string
  6548. //
  6549. hr = pVersion->GetVersion(L"IE", NULL, &cchVer);
  6550. ASSERT(hr == S_OK);
  6551. if (cchVer == 0)
  6552. {
  6553. // Not already set. Set it to default value.
  6554. // Note that the four digits of precision is required due to a peculiarity in the parser.
  6555. //
  6556. hr = pVersion->SetVersion(L"IE", L"6.0000");
  6557. }
  6558. return hr;
  6559. }
  6560. //+-------------------------------------------------------------------------
  6561. //
  6562. // Method : CBaseBrowser2::FindWindowByIndex
  6563. //
  6564. // Interface : ITravelLogClient
  6565. //
  6566. // Synopsis : Returns the window with the given index.
  6567. //
  6568. //--------------------------------------------------------------------------
  6569. HRESULT
  6570. CBaseBrowser2::FindWindowByIndex(DWORD dwID, IUnknown ** ppunk)
  6571. {
  6572. return GetBrowserByIndex(dwID, ppunk);
  6573. }
  6574. //+-------------------------------------------------------------------------
  6575. //
  6576. // Method : CBaseBrowser2::GetWindowData
  6577. //
  6578. // Interface : ITravelLogClient
  6579. //
  6580. // Synopsis : Returns a WINDOWDATA structure containing pertinent
  6581. // window information needed for the travel log..
  6582. //
  6583. //--------------------------------------------------------------------------
  6584. HRESULT
  6585. CBaseBrowser2::GetWindowData(LPWINDOWDATA pWinData)
  6586. {
  6587. HRESULT hr = S_OK;
  6588. ASSERT(pWinData);
  6589. ASSERT(_bbd._pidlCur);
  6590. DEBUG_CODE(TCHAR szPath[INTERNET_MAX_URL_LENGTH + 1];)
  6591. DEBUG_CODE(IEGetDisplayName(_bbd._pidlCur, szPath, SHGDN_FORPARSING);)
  6592. DEBUG_CODE(TraceMsg(DM_TRACE, "CBB::ActivatePendingView (TRAVELLOG): _UpdateTravelLog called from shdocvw for %ws", szPath);)
  6593. ZeroMemory(pWinData, sizeof(WINDOWDATA));
  6594. // Window ID and codepage
  6595. //
  6596. pWinData->dwWindowID = GetBrowserIndex();
  6597. pWinData->uiCP = _cp;
  6598. // Current Pidl
  6599. //
  6600. pWinData->pidl = ILClone(_bbd._pidlCur);
  6601. // Title - when we are in a shell view,
  6602. // _bbd._pszTitleCur is NULL, which is correct.
  6603. // However, we still have to create memory for
  6604. // pWinData->lpszTitle and you can't pass NULL
  6605. // to SHStrDupW.
  6606. //
  6607. if (_bbd._pszTitleCur)
  6608. hr = SHStrDupW(_bbd._pszTitleCur, &pWinData->lpszTitle);
  6609. return hr;
  6610. }
  6611. //+-------------------------------------------------------------------------
  6612. //
  6613. // Method : CBaseBrowser2::LoadHistoryPosition
  6614. //
  6615. // Interface : ITravelLogClient
  6616. //
  6617. // Synopsis : Loads the Url location and position cookie. This is used
  6618. // during a history navigation in a frame that involves a
  6619. // local anchor.
  6620. //
  6621. //--------------------------------------------------------------------------
  6622. HRESULT
  6623. CBaseBrowser2::LoadHistoryPosition(LPOLESTR pszUrlLocation, DWORD dwCookie)
  6624. {
  6625. IEPlaySound(TEXT("Navigating"), FALSE);
  6626. return SetPositionCookie(dwCookie);
  6627. }
  6628. //+-------------------------------------------------------------------------
  6629. //
  6630. // Method : CBaseBrowser2::GetDummyWindowData
  6631. //
  6632. // Interface : ITravelLogClient2
  6633. //
  6634. // Synopsis : Fills in a windowdata and a stream very similar to
  6635. // that created by SaveHistory.
  6636. // Be sure to keep this and SaveHistory in sync.
  6637. //
  6638. //--------------------------------------------------------------------------
  6639. STDMETHODIMP CBaseBrowser2::GetDummyWindowData(
  6640. LPWSTR pszUrl,
  6641. LPWSTR pszTitle,
  6642. LPWINDOWDATA pWinData)
  6643. {
  6644. HRESULT hres = S_OK;
  6645. PERSISTEDFRAME pf = {0};
  6646. LPITEMIDLIST pidl;
  6647. // grab current window ID
  6648. pWinData->dwWindowID = GetBrowserIndex();
  6649. // everything else is dummy
  6650. pWinData->uiCP = 0;
  6651. hres = SHStrDup(pszUrl, &pWinData->lpszUrl);
  6652. hres = SHStrDup(pszTitle, &pWinData->lpszTitle);
  6653. if (!pWinData->pStream)
  6654. {
  6655. hres = CreateStreamOnHGlobal(NULL, FALSE, &pWinData->pStream);
  6656. if (hres)
  6657. goto done;
  6658. }
  6659. pidl = PidlFromUrl(pszUrl);
  6660. pf.cbSize = SIZEOF(pf);
  6661. pf.bid = GetBrowserIndex();
  6662. pf.cbPidl = ILGetSize(pidl);
  6663. pf.type = PFTYPE_USEPIDL;
  6664. pf.lock = 0; // _bbd._eSecureLockIcon;
  6665. ASSERT(SUCCEEDED(IStream_Write(pWinData->pStream, (void *) c_szFrameMagic, CbFromCch(c_cchFrameMagic))));
  6666. if (SUCCEEDED(hres = IStream_Write(pWinData->pStream,(void *)&pf, pf.cbSize)))
  6667. hres = IStream_Write(pWinData->pStream,(void *)pidl, pf.cbPidl);
  6668. ILFree(pidl);
  6669. done:
  6670. return SUCCEEDED(hres) ? S_OK : E_FAIL;
  6671. }
  6672. //+-------------------------------------------------------------------------
  6673. //
  6674. // Method : CBaseBrowser2::UpdateDesktopComponent
  6675. //
  6676. // Interface : ITridentService
  6677. //
  6678. //--------------------------------------------------------------------------
  6679. HRESULT
  6680. CBaseBrowser2::UpdateDesktopComponent(IHTMLWindow2 * pHTMLWindow)
  6681. {
  6682. BSTR bstrTitle = NULL;
  6683. BSTR bstrUrlUnencoded = NULL;
  6684. HRESULT hr = S_OK;
  6685. IHTMLDocument2 * pHTMLDocument2;
  6686. IHTMLDocument4 * pHTMLDocument4;
  6687. DWORD dwOptions = 0;
  6688. hr = pHTMLWindow->get_document(&pHTMLDocument2);
  6689. if (SUCCEEDED(hr))
  6690. {
  6691. hr = pHTMLDocument2->QueryInterface(IID_PPV_ARG(IHTMLDocument4, &pHTMLDocument4));
  6692. if (SUCCEEDED(hr))
  6693. {
  6694. pHTMLDocument2->get_title(&bstrTitle);
  6695. pHTMLDocument4->get_URLUnencoded(&bstrUrlUnencoded);
  6696. TraceMsg(DM_TRACE, "CBaseBrowser2::UpdateDesktopComponent: URLUnencoded - %ws; Title - %ws",
  6697. bstrUrlUnencoded, bstrTitle);
  6698. // Update the desktop component's friendly name.
  6699. //
  6700. UpdateDesktopComponentName(bstrUrlUnencoded, bstrTitle);
  6701. SysFreeString(bstrTitle);
  6702. SysFreeString(bstrUrlUnencoded);
  6703. pHTMLDocument4->Release();
  6704. }
  6705. pHTMLDocument2->Release();
  6706. }
  6707. return hr;
  6708. }
  6709. HRESULT
  6710. CBaseBrowser2::_InitDocHost(IWebBrowser2 * pWebBrowser)
  6711. {
  6712. HRESULT hr = E_FAIL;
  6713. IDispatch* pDocDispatch = NULL;
  6714. ASSERT(pWebBrowser);
  6715. // get the IHTMLWindow2 for the WebOC windowop
  6716. hr = pWebBrowser->get_Document(&pDocDispatch);
  6717. if (S_OK == hr && pDocDispatch)
  6718. {
  6719. IHTMLDocument2* pDoc;
  6720. hr = pDocDispatch->QueryInterface(IID_PPV_ARG(IHTMLDocument2, &pDoc));
  6721. pDocDispatch->Release();
  6722. if (S_OK == hr)
  6723. {
  6724. IHTMLWindow2* pHtmlWindow;
  6725. hr = pDoc->get_parentWindow(&pHtmlWindow);
  6726. pDoc->Release();
  6727. if (S_OK == hr)
  6728. {
  6729. BOOL fIsFrameWindow = IsFrameWindow(pHtmlWindow);
  6730. pHtmlWindow->Release();
  6731. if (!fIsFrameWindow && _bbd._pctView)
  6732. {
  6733. hr = _bbd._pctView->Exec(&CGID_ShellDocView,
  6734. SHDVID_NAVSTART,
  6735. 0,
  6736. NULL,
  6737. NULL);
  6738. }
  6739. }
  6740. }
  6741. }
  6742. return hr;
  6743. }
  6744. //+-------------------------------------------------------------------------
  6745. //
  6746. // Method : CBaseBrowser2::FireBeforeNavigate2
  6747. //
  6748. // Interface : ITridentService
  6749. //
  6750. //--------------------------------------------------------------------------
  6751. HRESULT
  6752. CBaseBrowser2::FireBeforeNavigate2(IDispatch * pDispatch,
  6753. LPCTSTR lpszUrl,
  6754. DWORD dwFlags,
  6755. LPCTSTR lpszFrameName,
  6756. LPBYTE pPostData,
  6757. DWORD cbPostData,
  6758. LPCTSTR lpszHeaders,
  6759. BOOL fPlayNavSound,
  6760. BOOL * pfCancel)
  6761. {
  6762. HRESULT hr = S_OK;
  6763. BSTR bstrUrl = NULL;
  6764. LPITEMIDLIST pidl = NULL;
  6765. IWebBrowser2 * pWebBrowser = NULL;
  6766. ASSERT(pfCancel);
  6767. *pfCancel = FALSE;
  6768. // Stress fix
  6769. //
  6770. if (NULL == lpszUrl)
  6771. {
  6772. bstrUrl = SysAllocString(_T(""));
  6773. }
  6774. else
  6775. {
  6776. bstrUrl = SysAllocString(lpszUrl);
  6777. }
  6778. pidl = PidlFromUrl(bstrUrl);
  6779. if (pidl)
  6780. {
  6781. hr = _GetWebBrowserForEvt(pDispatch, &pWebBrowser);
  6782. if (S_OK == hr)
  6783. {
  6784. ASSERT(pWebBrowser);
  6785. _pidlBeforeNavigateEvent = pidl; // no need to copy.
  6786. // This is a work around for view linked weboc. Setting the frame name has side effects.
  6787. LPCTSTR pEffectiveName;
  6788. if (_fIsViewLinkedWebOC && (lpszFrameName == NULL || !lpszFrameName[0]))
  6789. {
  6790. pEffectiveName = _szViewLinkedWebOCFrameName;
  6791. }
  6792. else
  6793. {
  6794. pEffectiveName = lpszFrameName;
  6795. }
  6796. FireEvent_BeforeNavigate(pWebBrowser, _bbd._hwnd, pWebBrowser,
  6797. pidl, NULL, dwFlags, pEffectiveName,
  6798. pPostData, cbPostData, lpszHeaders, pfCancel);
  6799. // Make sure that we remove earlier URLs that are cached during redirections.
  6800. _InitDocHost(pWebBrowser);
  6801. ATOMICRELEASE(pWebBrowser);
  6802. ASSERT(_pidlBeforeNavigateEvent == pidl);
  6803. _pidlBeforeNavigateEvent = NULL;
  6804. ILFree(pidl);
  6805. if (!*pfCancel && fPlayNavSound)
  6806. {
  6807. IEPlaySound(TEXT("Navigating"), FALSE);
  6808. }
  6809. }
  6810. }
  6811. if (_phtmlWS && !pDispatch)
  6812. {
  6813. if (!_bbd._psvPending)
  6814. {
  6815. _phtmlWS->ViewReleased();
  6816. }
  6817. else
  6818. {
  6819. _phtmlWS->ViewReleaseIntelliForms();
  6820. }
  6821. }
  6822. else if (_phtmlWS && !_bbd._psvPending)
  6823. {
  6824. _DismissFindDialog();
  6825. }
  6826. SysFreeString(bstrUrl);
  6827. return hr;
  6828. }
  6829. //+-------------------------------------------------------------------------
  6830. //
  6831. // Method : CBaseBrowser2::FireNavigateError
  6832. //
  6833. // Interface : ITridentService2
  6834. //
  6835. // Called when there is a binding error
  6836. //
  6837. // Input : pHTMLWindow - used to determine if we are a frame or
  6838. // the top-level.
  6839. // bstrURL - the URL which caused the error.
  6840. // bstrTargetFrameName - the frame being targeted.
  6841. // dwStatusCode - the binding error
  6842. // pfCancel - set by the host if it wants to
  6843. // cancel autosearch or friendly error
  6844. // pages
  6845. //
  6846. //--------------------------------------------------------------------------
  6847. HRESULT
  6848. CBaseBrowser2::FireNavigateError(IHTMLWindow2 * pHTMLWindow2,
  6849. BSTR bstrURL,
  6850. BSTR bstrTargetFrameName,
  6851. DWORD dwStatusCode,
  6852. BOOL * pfCancel)
  6853. {
  6854. ASSERT(dwStatusCode != 0);
  6855. HRESULT hr = S_OK;
  6856. IWebBrowser2 * pWebBrowser = NULL;
  6857. *pfCancel = FALSE;
  6858. //
  6859. // Use top-level if window is not specified or the window is the top-level
  6860. //
  6861. if ((pHTMLWindow2 != NULL) && IsFrameWindow(pHTMLWindow2))
  6862. {
  6863. hr = _GetWebBrowserForEvt(pHTMLWindow2, &pWebBrowser);
  6864. }
  6865. else
  6866. {
  6867. hr = _GetWebBrowserForEvt(NULL, &pWebBrowser);
  6868. }
  6869. if (S_OK == hr)
  6870. {
  6871. ASSERT(pWebBrowser);
  6872. TCHAR szUrl[INTERNET_MAX_URL_LENGTH];
  6873. LPITEMIDLIST pidl = NULL;
  6874. if (bstrURL)
  6875. {
  6876. StrCpyN(szUrl, bstrURL, ARRAYSIZE(szUrl));
  6877. }
  6878. else
  6879. {
  6880. StrCpyN(szUrl, _T(""), ARRAYSIZE(szUrl));
  6881. }
  6882. pidl = PidlFromUrl(szUrl);
  6883. if (pidl)
  6884. {
  6885. FireEvent_NavigateError(pWebBrowser,
  6886. pWebBrowser,
  6887. pidl,
  6888. bstrTargetFrameName,
  6889. dwStatusCode,
  6890. pfCancel);
  6891. ILFree(pidl);
  6892. }
  6893. }
  6894. ATOMICRELEASE(pWebBrowser);
  6895. return hr;
  6896. }
  6897. //+-------------------------------------------------------------------------
  6898. //
  6899. // Method : CBaseBrowser2::FirePrintTemplateEvent
  6900. //
  6901. // Interface : ITridentService
  6902. //
  6903. // Called when a template is instantiate or torndown
  6904. //
  6905. // pHTMLWindow is used to determine if we are a frame or the top-level
  6906. // dispidPrintEvent either DISPID_PRINTTEMPLATEINSTANTIATION
  6907. // or DISPID_PRINTTEMPLATETEARDOWN
  6908. //
  6909. //--------------------------------------------------------------------------
  6910. HRESULT
  6911. CBaseBrowser2::FirePrintTemplateEvent(IHTMLWindow2 * pHTMLWindow2, DISPID dispidPrintEvent)
  6912. {
  6913. HRESULT hr = S_OK;
  6914. IWebBrowser2 * pWebBrowser = NULL;
  6915. //
  6916. // Use top-level if window is not specified or the window is the top-level
  6917. //
  6918. if ((pHTMLWindow2 != NULL) && IsFrameWindow(pHTMLWindow2))
  6919. {
  6920. hr = _GetWebBrowserForEvt(pHTMLWindow2, &pWebBrowser);
  6921. }
  6922. else
  6923. {
  6924. hr = _GetWebBrowserForEvt(NULL, &pWebBrowser);
  6925. }
  6926. if (S_OK == hr)
  6927. {
  6928. ASSERT(pWebBrowser);
  6929. FireEvent_PrintTemplateEvent(pWebBrowser,
  6930. pWebBrowser,
  6931. dispidPrintEvent);
  6932. }
  6933. ATOMICRELEASE(pWebBrowser);
  6934. return hr;
  6935. }
  6936. //+-------------------------------------------------------------------------
  6937. //
  6938. // Method : CBaseBrowser2::FireUpdatePageStatus
  6939. //
  6940. // Interface : ITridentService
  6941. //
  6942. // Called when a template is instantiate or torndown
  6943. //
  6944. // pHTMLWindow is used to determine if we are a frame or the top-level
  6945. // nPage defined to be the number of pages spooled
  6946. // fDone a flag to indicate that the last page has been sppoled
  6947. //
  6948. //--------------------------------------------------------------------------
  6949. HRESULT
  6950. CBaseBrowser2::FireUpdatePageStatus(IHTMLWindow2 * pHTMLWindow2, DWORD nPage, BOOL fDone)
  6951. {
  6952. HRESULT hr = S_OK;
  6953. IWebBrowser2 * pWebBrowser = NULL;
  6954. //
  6955. // Use top-level if window is not specified or the window is the top-level
  6956. //
  6957. if ((pHTMLWindow2 != NULL) && IsFrameWindow(pHTMLWindow2))
  6958. {
  6959. hr = _GetWebBrowserForEvt(pHTMLWindow2, &pWebBrowser);
  6960. }
  6961. else
  6962. {
  6963. hr = _GetWebBrowserForEvt(NULL, &pWebBrowser);
  6964. }
  6965. if (S_OK == hr)
  6966. {
  6967. ASSERT(pWebBrowser);
  6968. FireEvent_UpdatePageStatus(pWebBrowser,
  6969. pWebBrowser,
  6970. nPage,
  6971. fDone);
  6972. }
  6973. ATOMICRELEASE(pWebBrowser);
  6974. return hr;
  6975. }
  6976. //+-------------------------------------------------------------------------
  6977. //
  6978. // Method : CBaseBrowser2::FirePrivacyImpactedStateChange
  6979. //
  6980. // Interface : ITridentService2
  6981. //
  6982. // Called whenever the global privacy impacted state changes
  6983. //
  6984. // Input : The new privacy impacted state
  6985. //
  6986. //--------------------------------------------------------------------------
  6987. HRESULT
  6988. CBaseBrowser2::FirePrivacyImpactedStateChange(BOOL bPrivacyImpacted)
  6989. {
  6990. HRESULT hr = S_OK;
  6991. IWebBrowser2 * pWebBrowser = NULL;
  6992. //
  6993. // Update browser frame / save state
  6994. //
  6995. _UpdatePrivacyIcon(TRUE, bPrivacyImpacted);
  6996. //
  6997. // We always fire this at the top level
  6998. //
  6999. hr = _GetWebBrowserForEvt(NULL, &pWebBrowser);
  7000. if (S_OK == hr)
  7001. {
  7002. ASSERT(pWebBrowser);
  7003. FireEvent_PrivacyImpactedStateChange(pWebBrowser,
  7004. bPrivacyImpacted);
  7005. }
  7006. ATOMICRELEASE(pWebBrowser);
  7007. return hr;
  7008. }
  7009. HRESULT
  7010. CBaseBrowser2::_DismissFindDialog()
  7011. {
  7012. BSTR bstrName = SysAllocString(STR_FIND_DIALOG_NAME);
  7013. if (bstrName)
  7014. {
  7015. VARIANT varProp = {0};
  7016. _bbd._pautoWB2->GetProperty(bstrName, &varProp);
  7017. if ( (varProp.vt == VT_DISPATCH) && (varProp.pdispVal != NULL) )
  7018. {
  7019. IUnknown* pWindow = varProp.pdispVal;
  7020. //now that we've pulled the pdispVal out of the propbag, clear the property on the automation object
  7021. VARIANT varTmp = {0};
  7022. _bbd._pautoWB2->PutProperty(bstrName, varTmp);
  7023. //(davemi) see IE5 bug 57060 for why the below line doesn't work and IDispatch must be used instead
  7024. //pWindow->close();
  7025. IDispatch * pdisp;
  7026. if (SUCCEEDED(pWindow->QueryInterface(IID_PPV_ARG(IDispatch, &pdisp))))
  7027. {
  7028. DISPID dispid;
  7029. DISPPARAMS dispparamsNoArgs = {NULL, NULL, 0, 0};
  7030. BSTR bstrClose = SysAllocString(L"close");
  7031. if (bstrClose)
  7032. {
  7033. HRESULT hr;
  7034. hr = pdisp->GetIDsOfNames(IID_NULL, &bstrClose, 1, LOCALE_SYSTEM_DEFAULT, &dispid);
  7035. if (hr == S_OK)
  7036. pdisp->Invoke(dispid, IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_METHOD, &dispparamsNoArgs, &varTmp, NULL, NULL);
  7037. SysFreeString(bstrClose);
  7038. }
  7039. pdisp->Release();
  7040. }
  7041. }
  7042. VariantClear(&varProp);
  7043. SysFreeString(bstrName);
  7044. }
  7045. return S_OK;
  7046. }
  7047. //+-------------------------------------------------------------------------
  7048. //
  7049. // Method : CBaseBrowser2::_GetWebBrowserForEvt
  7050. //
  7051. //--------------------------------------------------------------------------
  7052. HRESULT
  7053. CBaseBrowser2::_GetWebBrowserForEvt(IDispatch * pDispatch,
  7054. IWebBrowser2 ** ppWebBrowser)
  7055. {
  7056. if (_fIsViewLinkedWebOC && _pDispViewLinkedWebOCFrame && _fHadFirstBeforeNavigate)
  7057. {
  7058. *ppWebBrowser = _pDispViewLinkedWebOCFrame;
  7059. _pDispViewLinkedWebOCFrame->AddRef();
  7060. return S_OK;
  7061. }
  7062. else if (pDispatch) // Top-level
  7063. {
  7064. return IUnknown_QueryService(pDispatch,
  7065. SID_SWebBrowserApp,
  7066. IID_PPV_ARG(IWebBrowser2, ppWebBrowser));
  7067. }
  7068. else
  7069. {
  7070. *ppWebBrowser = _bbd._pautoWB2;
  7071. if (*ppWebBrowser)
  7072. {
  7073. (*ppWebBrowser)->AddRef();
  7074. return S_OK;
  7075. }
  7076. return E_FAIL;
  7077. }
  7078. }
  7079. //+-------------------------------------------------------------------------
  7080. //
  7081. // Method : CBaseBrowser2::GetUrlSearchComponent
  7082. //
  7083. // Interface : ITridentService
  7084. //
  7085. //--------------------------------------------------------------------------
  7086. HRESULT
  7087. CBaseBrowser2::GetUrlSearchComponent(BSTR * pbstrSearch)
  7088. {
  7089. TCHAR sz[MAX_URL_STRING];
  7090. ASSERT(pbstrSearch);
  7091. ASSERT(!*pbstrSearch);
  7092. if (ILGetHiddenString(_bbd._pidlPending ? _bbd._pidlPending : _bbd._pidlCur,
  7093. IDLHID_URLQUERY,
  7094. sz,
  7095. SIZECHARS(sz)))
  7096. {
  7097. *pbstrSearch = SysAllocString(sz);
  7098. }
  7099. return (*pbstrSearch) ? S_OK : E_FAIL;
  7100. }
  7101. //+-------------------------------------------------------------------------
  7102. //
  7103. // Method : CBaseBrowser2::IsErrorUrl
  7104. //
  7105. // Interface : ITridentService
  7106. //
  7107. //--------------------------------------------------------------------------
  7108. HRESULT
  7109. CBaseBrowser2::IsErrorUrl(LPCTSTR lpszUrl, BOOL *pfIsError)
  7110. {
  7111. HRESULT hr = S_OK;
  7112. if (!lpszUrl || !pfIsError)
  7113. {
  7114. hr = E_INVALIDARG;
  7115. goto Cleanup;
  7116. }
  7117. *pfIsError = ::IsErrorUrl(lpszUrl);
  7118. Cleanup:
  7119. return hr;
  7120. }
  7121. //+-------------------------------------------------------------------------
  7122. //
  7123. // Method : CBaseBrowser2::FireNavigateComplete2
  7124. //
  7125. // Interface : ITridentService
  7126. //
  7127. //--------------------------------------------------------------------------
  7128. HRESULT
  7129. CBaseBrowser2::FireNavigateComplete2(IHTMLWindow2 * pHTMLWindow2,
  7130. DWORD dwFlags)
  7131. {
  7132. if (!pHTMLWindow2)
  7133. return E_POINTER;
  7134. HRESULT hr = E_FAIL;
  7135. BOOL fIsErrorUrl = FALSE;
  7136. BSTR bstrUrl = GetHTMLWindowUrl(pHTMLWindow2);
  7137. if (bstrUrl)
  7138. {
  7139. // If the URL is a res: URL, _GetPidlForDisplay will return
  7140. // the URL after the # in the res: URL.
  7141. //
  7142. LPITEMIDLIST pidl = _GetPidlForDisplay(bstrUrl, &fIsErrorUrl);
  7143. if (pidl)
  7144. {
  7145. BOOL fViewActivated = FALSE;
  7146. IWebBrowser2 * pWebBrowser = NULL;
  7147. // If this is not a frame, we update the browser
  7148. // state and pass the browser's IWebBrowser2 to
  7149. // FireEvent_NavigateComplete. If this is a frame,
  7150. // we pass the IWebBrowser2 of the window.
  7151. //
  7152. if (!(dwFlags & NAVDATA_FRAMEWINDOW))
  7153. {
  7154. fViewActivated = _ActivateView(bstrUrl, pidl, dwFlags, fIsErrorUrl);
  7155. if (_dwDocFlags & DOCFLAG_DOCCANNAVIGATE)
  7156. {
  7157. ATOMICRELEASE(_pHTMLDocument);
  7158. pHTMLWindow2->get_document(&_pHTMLDocument);
  7159. }
  7160. if (IEHard_ShowOnNavigateComplete())
  7161. {
  7162. EnableModelessSB(FALSE);
  7163. IEHard_NavWarning(_bbd._hwnd, IEHard_HostedInIE((IShellBrowser*)this));
  7164. EnableModelessSB(TRUE);
  7165. }
  7166. }
  7167. else
  7168. {
  7169. if (IsWindowVisible(_bbd._hwnd)
  7170. && !(_dwSBSPQueued & SBSP_WRITENOHISTORY)
  7171. && !(dwFlags & NAVDATA_FRAMECREATION)
  7172. && !(dwFlags & NAVDATA_RESTARTLOAD))
  7173. {
  7174. IEPlaySound(TEXT("ActivatingDocument"), FALSE);
  7175. }
  7176. if (_pbsOuter)
  7177. {
  7178. _pbsOuter->UpdateBackForwardState();
  7179. }
  7180. }
  7181. hr = _GetWebBrowserForEvt((dwFlags & NAVDATA_FRAMEWINDOW) ? pHTMLWindow2 : NULL,
  7182. &pWebBrowser);
  7183. if (S_OK == hr && !fViewActivated)
  7184. {
  7185. ASSERT(pWebBrowser);
  7186. // fire the event!
  7187. FireEvent_NavigateComplete(pWebBrowser, pWebBrowser, pidl, _bbd._hwnd);
  7188. }
  7189. ATOMICRELEASE(pWebBrowser);
  7190. ILFree(pidl);
  7191. }
  7192. SysFreeString(bstrUrl);
  7193. }
  7194. return hr;
  7195. }
  7196. //+-------------------------------------------------------------------------
  7197. //
  7198. // Method : CBaseBrowser2::_ActivateView
  7199. //
  7200. // Synopsis : If there is a pending view, it will be activated. If there
  7201. // if not a pending view, which is the case when we are
  7202. // navigating due to a hyperlink, OM navigation, or frame
  7203. // navigation, we update the browser state. (The view is already
  7204. // active in this case.) In either case, we update the
  7205. // state of the dochost.
  7206. //
  7207. //--------------------------------------------------------------------------
  7208. BOOL
  7209. CBaseBrowser2::_ActivateView(BSTR bstrUrl,
  7210. LPITEMIDLIST pidl,
  7211. DWORD dwFlags,
  7212. BOOL fIsErrorUrl)
  7213. {
  7214. BOOL fViewActivated = FALSE;
  7215. // Activate the pending view if there is one.
  7216. //
  7217. if (_bbd._psvPending)
  7218. {
  7219. ILFree(_bbd._pidlPending);
  7220. _bbd._pidlPending = ILClone(pidl);
  7221. _fDontUpdateTravelLog = !!(dwFlags & NAVDATA_DONTUPDATETRAVELLOG);
  7222. ASSERT(_pbsOuter);
  7223. _pbsOuter->ActivatePendingView();
  7224. _fDontUpdateTravelLog = FALSE;
  7225. fViewActivated = TRUE;
  7226. }
  7227. else
  7228. {
  7229. UINT uProt = GetUrlSchemeW(bstrUrl);
  7230. if ( uProt != URL_SCHEME_JAVASCRIPT
  7231. && uProt != URL_SCHEME_VBSCRIPT)
  7232. {
  7233. _UpdateBrowserState(pidl);
  7234. }
  7235. // In the case where there is a pending view
  7236. // ActivatePendingView() will call ViewActivated().
  7237. // Also, the call to ViewActivated() must happen
  7238. // after the current pidl has changed. The current
  7239. // pidl changes in _UpdateBrowserState().
  7240. //
  7241. if (_phtmlWS)
  7242. {
  7243. _phtmlWS->ViewActivated();
  7244. }
  7245. // Don't play sound for the first navigation (to avoid multiple
  7246. // sounds to be played for a frame-set creation).
  7247. //
  7248. ASSERT(_bbd._psv);
  7249. if (IsWindowVisible(_bbd._hwnd) && !(_dwSBSPQueued & SBSP_WRITENOHISTORY))
  7250. {
  7251. IEPlaySound(TEXT("ActivatingDocument"), FALSE);
  7252. }
  7253. }
  7254. // In the case of an error URL, we must send the original URL
  7255. // to the dochost. It needs the res: URL in the case of an
  7256. // error page so it knows not to update the history.
  7257. //
  7258. if (!fIsErrorUrl)
  7259. {
  7260. _UpdateDocHostState(pidl, fIsErrorUrl);
  7261. }
  7262. else
  7263. {
  7264. LPITEMIDLIST pidlOriginal = PidlFromUrl(bstrUrl);
  7265. if (pidlOriginal)
  7266. {
  7267. _UpdateDocHostState(pidlOriginal, fIsErrorUrl);
  7268. ILFree(pidlOriginal);
  7269. }
  7270. }
  7271. if (_pbsOuter)
  7272. {
  7273. _pbsOuter->_OnFocusChange(ITB_VIEW);
  7274. }
  7275. return fViewActivated;
  7276. }
  7277. //+-------------------------------------------------------------------------
  7278. //
  7279. // Method : CBaseBrowser2::_UpdateBrowserState
  7280. //
  7281. //--------------------------------------------------------------------------
  7282. void
  7283. CBaseBrowser2::_UpdateBrowserState(LPCITEMIDLIST pidl)
  7284. {
  7285. ASSERT(pidl);
  7286. ILFree(_bbd._pidlCur);
  7287. _bbd._pidlCur = ILClone(pidl);
  7288. // With the _bbd._pidlCur now updated, we can now call UpdateWindowList to
  7289. // update the window list with the new pidl.
  7290. //
  7291. _pbsOuter->UpdateWindowList();
  7292. _fGeneratedPage = FALSE;
  7293. }
  7294. //+-------------------------------------------------------------------------
  7295. //
  7296. // Method : CBaseBrowser2::_UpdateDocHostState
  7297. //
  7298. //--------------------------------------------------------------------------
  7299. void
  7300. CBaseBrowser2::_UpdateDocHostState(LPITEMIDLIST pidl, BOOL fIsErrorUrl) const
  7301. {
  7302. DOCHOSTUPDATEDATA dhud;
  7303. VARIANT varVal;
  7304. ASSERT( (_bbd._psvPending && _bbd._pidlPending)
  7305. || (!_bbd._psvPending && !_bbd._pidlPending));
  7306. ASSERT(!_bbd._pidlPending || ILIsEqual(_bbd._pidlPending, pidl) || fIsErrorUrl);
  7307. IShellView * psv = _bbd._psvPending ? _bbd._psvPending : _bbd._psv;
  7308. ASSERT(psv);
  7309. dhud._pidl = pidl;
  7310. dhud._fIsErrorUrl = fIsErrorUrl;
  7311. varVal.vt = VT_PTR;
  7312. varVal.byref = &dhud;
  7313. IUnknown_Exec(psv, &CGID_ShellDocView,
  7314. SHDVID_UPDATEDOCHOSTSTATE, 0, &varVal, NULL);
  7315. }
  7316. //+-------------------------------------------------------------------------
  7317. //
  7318. // Method : CBaseBrowser2::FireDocumentComplete
  7319. //
  7320. // Interface : ITridentService
  7321. //
  7322. //--------------------------------------------------------------------------
  7323. HRESULT
  7324. CBaseBrowser2::FireDocumentComplete(IHTMLWindow2 * pHTMLWindow2,
  7325. DWORD dwFlags)
  7326. {
  7327. if (!pHTMLWindow2)
  7328. return E_POINTER;
  7329. HRESULT hr = E_FAIL;
  7330. BSTR bstrUrl = GetHTMLWindowUrl(pHTMLWindow2);
  7331. if (bstrUrl)
  7332. {
  7333. LPITEMIDLIST pidl = _GetPidlForDisplay(bstrUrl);
  7334. if (pidl)
  7335. {
  7336. IWebBrowser2 * pWebBrowser;
  7337. hr = _GetWebBrowserForEvt((dwFlags & NAVDATA_FRAMEWINDOW) ? pHTMLWindow2 : NULL,
  7338. &pWebBrowser);
  7339. ASSERT(pWebBrowser);
  7340. if (S_OK == hr)
  7341. {
  7342. FireEvent_DocumentComplete(pWebBrowser, pWebBrowser, pidl);
  7343. pWebBrowser->Release();
  7344. }
  7345. ILFree(pidl);
  7346. }
  7347. SysFreeString(bstrUrl);
  7348. }
  7349. if (!(dwFlags & NAVDATA_FRAMEWINDOW) && !IEHard_ShowOnNavigateComplete())
  7350. {
  7351. if (_CanShowModalDialogNow())
  7352. {
  7353. // Even if we think we can, don't do it from inside DocumentComplete or any other Trident event.
  7354. // Pumping messages during any of these events is bad for Trident, so we'll do it slightly later.
  7355. PostMessage(_bbd._hwnd, WMC_IEHARD_NAVWARNING, 0, 0);
  7356. }
  7357. }
  7358. return hr;
  7359. }
  7360. // Determines if we are in a reasonable state to show a random dialog box out of nowhere.
  7361. // The browser can get into states where the window is basically useless and no view
  7362. // is hosted. One such case is when a new window navigates to unhostable content
  7363. // (like an exe file). If we put up a dialog at a bad time, we'll disrupt some sensitive
  7364. // Trident timing and the content won't be sent to the download dialog.
  7365. BOOL CBaseBrowser2::_CanShowModalDialogNow()
  7366. {
  7367. return (_bbd._hwnd && IsWindow(_bbd._hwnd) && IsWindowVisible(_bbd._hwnd) &&
  7368. _bbd._hwndView && IsWindow(_bbd._hwndView) && IsWindowVisible(_bbd._hwndView));
  7369. }
  7370. void CBaseBrowser2::_ShowIEHardNavWarning()
  7371. {
  7372. if (_CanShowModalDialogNow())
  7373. {
  7374. // If GetLastActivePopup returns something other than the supplied window, it means
  7375. // there is a modal or modeless dialog that is active, and we don't bother showing any message.
  7376. HWND hwndPopup = GetLastActivePopup(_bbd._hwnd);
  7377. if (hwndPopup == _bbd._hwnd)
  7378. {
  7379. // Most of the time, this means that there are no dialogs attached to us.
  7380. // But there could still be a modeless dialog showing; it just isn't active right now.
  7381. // We'll show our messagebox anyway, because the same thing would happen if you opened
  7382. // the About dialog yourself -- it would be parented to the top window, and the modeless
  7383. // dialog would still be dangling around and enabled.
  7384. EnableModelessSB(FALSE);
  7385. IEHard_NavWarning(_bbd._hwnd, IEHard_HostedInIE((IShellBrowser*)this));
  7386. EnableModelessSB(TRUE);
  7387. }
  7388. }
  7389. }
  7390. //+-------------------------------------------------------------------------
  7391. //
  7392. // Method : CBaseBrowser2::FireDownloadBegin
  7393. //
  7394. // Interface : ITridentService
  7395. //
  7396. //--------------------------------------------------------------------------
  7397. HRESULT
  7398. CBaseBrowser2::FireDownloadBegin()
  7399. {
  7400. return _updateNavigationUI();
  7401. }
  7402. //+-------------------------------------------------------------------------
  7403. //
  7404. // Method : CBaseBrowser2::FireDownloadComplete
  7405. //
  7406. // Interface : ITridentService
  7407. //
  7408. //--------------------------------------------------------------------------
  7409. HRESULT
  7410. CBaseBrowser2::FireDownloadComplete()
  7411. {
  7412. return _updateNavigationUI();
  7413. }
  7414. //+-------------------------------------------------------------------------
  7415. //
  7416. // Method : CBaseBrowser2::GetPendingUrl
  7417. //
  7418. // Interface : ITridentService
  7419. //
  7420. //--------------------------------------------------------------------------
  7421. HRESULT
  7422. CBaseBrowser2::GetPendingUrl(BSTR * pbstrPendingUrl)
  7423. {
  7424. if (!pbstrPendingUrl)
  7425. return E_POINTER;
  7426. *pbstrPendingUrl = NULL;
  7427. LPITEMIDLIST pidl = _bbd._pidlPending ? _bbd._pidlPending : _bbd._pidlCur;
  7428. TCHAR szPath[INTERNET_MAX_URL_LENGTH + 1];
  7429. HRESULT hr = IEGetDisplayName(pidl, szPath, SHGDN_FORPARSING);
  7430. if (S_OK == hr)
  7431. {
  7432. TraceMsg(DM_TRACE, "CBaseBrowser2::GetPendingUrl - URL: %ws", szPath);
  7433. *pbstrPendingUrl = SysAllocString(szPath);
  7434. }
  7435. return (*pbstrPendingUrl) ? S_OK : E_FAIL;
  7436. }
  7437. //+-------------------------------------------------------------------------
  7438. //
  7439. // Method : CBaseBrowser2::ActiveElementChanged
  7440. //
  7441. // Interface : ITridentService
  7442. //
  7443. //--------------------------------------------------------------------------
  7444. HRESULT
  7445. CBaseBrowser2::ActiveElementChanged(IHTMLElement * pHTMLElement)
  7446. {
  7447. // Forward the call to the OmWindow
  7448. //
  7449. if (_phtmlWS)
  7450. {
  7451. return _phtmlWS->ActiveElementChanged(pHTMLElement);
  7452. }
  7453. return E_FAIL;
  7454. }
  7455. //+-------------------------------------------------------------------------
  7456. //
  7457. // Method : CBaseBrowser2::InitAutoImageResize()
  7458. //
  7459. // Interface : ITridentService2
  7460. //
  7461. //--------------------------------------------------------------------------
  7462. HRESULT
  7463. CBaseBrowser2::InitAutoImageResize()
  7464. {
  7465. HRESULT hr = S_OK;
  7466. if (_pAIResize)
  7467. UnInitAutoImageResize();
  7468. CAutoImageResize *pAIResize = new CAutoImageResize();
  7469. if (pAIResize)
  7470. {
  7471. // need to get a pDoc2 for the init call...
  7472. IDispatch *pDocDispatch;
  7473. hr = _bbd._pautoWB2->get_Document(&pDocDispatch);
  7474. if (SUCCEEDED(hr))
  7475. {
  7476. IHTMLDocument2 *pDoc2;
  7477. hr = pDocDispatch->QueryInterface(IID_PPV_ARG(IHTMLDocument2,&pDoc2));
  7478. if (SUCCEEDED(hr))
  7479. {
  7480. // init the object
  7481. pAIResize->Init(pDoc2);
  7482. // cache the pointer for destruction later
  7483. _pAIResize=pAIResize;
  7484. pDoc2->Release();
  7485. }
  7486. pDocDispatch->Release();
  7487. }
  7488. if (FAILED(hr))
  7489. {
  7490. delete pAIResize;
  7491. }
  7492. }
  7493. else
  7494. hr = E_OUTOFMEMORY;
  7495. return hr;
  7496. }
  7497. //+-------------------------------------------------------------------------
  7498. //
  7499. // Method : CBaseBrowser2::UnInitAutoImageResize()
  7500. //
  7501. // Interface : ITridentService2
  7502. //
  7503. //--------------------------------------------------------------------------
  7504. HRESULT
  7505. CBaseBrowser2::UnInitAutoImageResize()
  7506. {
  7507. if (_pAIResize)
  7508. {
  7509. _pAIResize->UnInit();
  7510. ATOMICRELEASE(_pAIResize);
  7511. }
  7512. return S_OK;
  7513. }
  7514. //+-------------------------------------------------------------------------
  7515. //
  7516. // Method : CBaseBrowser2::IsGalleryMeta
  7517. //
  7518. // Interface : ITridentService2
  7519. //
  7520. //--------------------------------------------------------------------------
  7521. HRESULT
  7522. CBaseBrowser2::IsGalleryMeta(BOOL bFlag, void *pMyPics)
  7523. {
  7524. // Forward the call to the CMyPics object
  7525. //
  7526. if (pMyPics)
  7527. {
  7528. ((CMyPics*)pMyPics)->IsGalleryMeta(bFlag);
  7529. return S_OK;
  7530. }
  7531. return E_FAIL;
  7532. }
  7533. //+-------------------------------------------------------------------------
  7534. //
  7535. // Functions that live in mypics.cpp that are called below
  7536. //
  7537. //--------------------------------------------------------------------------
  7538. HRESULT SendDocToMailRecipient(LPCITEMIDLIST pidl, UINT uiCodePage, DWORD grfKeyState, IUnknown *pUnkSite);
  7539. BOOL MP_IsEnabledInIEAK();
  7540. BOOL MP_IsEnabledInRegistry();
  7541. //+-------------------------------------------------------------------------
  7542. //
  7543. // Method : CBaseBrowser2::EmailPicture
  7544. //
  7545. // Interface : ITridentService2
  7546. //
  7547. //--------------------------------------------------------------------------
  7548. HRESULT
  7549. CBaseBrowser2::EmailPicture(BSTR bstrURL)
  7550. {
  7551. IDispatch *pDocDispatch;
  7552. HRESULT hr = _bbd._pautoWB2->get_Document(&pDocDispatch);
  7553. if (SUCCEEDED(hr))
  7554. {
  7555. IHTMLDocument2 *pDoc2;
  7556. hr = pDocDispatch->QueryInterface(IID_PPV_ARG(IHTMLDocument2, &pDoc2));
  7557. if (SUCCEEDED(hr))
  7558. {
  7559. // Get that cmd target thingie...
  7560. IOleCommandTarget *pcmdt;
  7561. hr = IUnknown_QueryService(pDoc2, SID_SWebBrowserApp, IID_PPV_ARG(IOleCommandTarget, &pcmdt));
  7562. if (SUCCEEDED(hr))
  7563. {
  7564. // ... and thus the pidl...
  7565. LPITEMIDLIST pidlForImg;
  7566. hr = IEParseDisplayName(CP_ACP, bstrURL, &pidlForImg);
  7567. if (SUCCEEDED(hr))
  7568. {
  7569. // ... and pray this works...
  7570. SendDocToMailRecipient(pidlForImg, 0, FORCE_COPY, pcmdt);
  7571. ILFree(pidlForImg);
  7572. }
  7573. pcmdt->Release();
  7574. }
  7575. pDoc2->Release();
  7576. }
  7577. pDocDispatch->Release();
  7578. }
  7579. return hr;
  7580. }
  7581. //+-------------------------------------------------------------------------
  7582. //
  7583. // Method : CBaseBrowser2::AttachMyPics
  7584. //
  7585. // Interface : ITridentService2
  7586. //
  7587. //--------------------------------------------------------------------------
  7588. HRESULT
  7589. CBaseBrowser2::AttachMyPics(void *pDoc2, void **ppMyPics)
  7590. {
  7591. IHTMLDocument2 *pdoc2 = (IHTMLDocument2 *)pDoc2;
  7592. DWORD dwOptions = 0;
  7593. ASSERT(ppMyPics && *ppMyPics==NULL);
  7594. if (!MP_IsEnabledInIEAK() ||
  7595. !MP_IsEnabledInRegistry() ||
  7596. !IsInternetExplorerApp())
  7597. {
  7598. return S_OK;
  7599. }
  7600. if (!pdoc2 || !ppMyPics || (*ppMyPics != NULL))
  7601. {
  7602. return S_OK;
  7603. }
  7604. //Is this a desktop component?
  7605. if (SUCCEEDED(GetTopFrameOptions(_pspOuter, &dwOptions)))
  7606. {
  7607. if (dwOptions & FRAMEOPTIONS_DESKTOP)
  7608. {
  7609. return S_OK;
  7610. }
  7611. }
  7612. CMyPics *pPics = new CMyPics();
  7613. if (pPics)
  7614. {
  7615. if (SUCCEEDED(pPics->Init(pdoc2)))
  7616. {
  7617. *ppMyPics = pPics;
  7618. }
  7619. else
  7620. {
  7621. pPics->Release();
  7622. }
  7623. }
  7624. return S_OK;
  7625. }
  7626. //+-------------------------------------------------------------------------
  7627. //
  7628. // Method : CBaseBrowser2::ReleaseMyPics
  7629. //
  7630. // Interface : ITridentService2
  7631. //
  7632. //--------------------------------------------------------------------------
  7633. BOOL
  7634. CBaseBrowser2::ReleaseMyPics(void *pMyPics)
  7635. {
  7636. CMyPics *pPics = (CMyPics *) pMyPics;
  7637. BOOL bRet = pPics->IsOff();
  7638. if (pPics)
  7639. {
  7640. pPics->UnInit();
  7641. pPics->Release();
  7642. }
  7643. return (bRet);
  7644. }
  7645. STDMETHODIMP CBaseBrowser2::SetFrameName(BSTR bstrFrameName)
  7646. {
  7647. return StringCchCopy(_szViewLinkedWebOCFrameName, ARRAYSIZE(_szViewLinkedWebOCFrameName), bstrFrameName);
  7648. }
  7649. //+-------------------------------------------------------------------------
  7650. //
  7651. // Method : CBaseBrowser2::AppStarting
  7652. //
  7653. // Interface : INotifyAppStart
  7654. //
  7655. //--------------------------------------------------------------------------
  7656. HRESULT
  7657. CBaseBrowser2::AppStarting(void)
  7658. {
  7659. _dwStartingAppTick = GetTickCount();
  7660. SetCursor(LoadCursor(NULL, IDC_APPSTARTING));
  7661. SetTimer( _bbd._hwnd, IDT_STARTING_APP_TIMER, STARTING_APP_DURATION, NULL);
  7662. return S_OK;
  7663. }
  7664. //+-------------------------------------------------------------------------
  7665. //
  7666. // Method : CBaseBrowser2::AppStarted
  7667. //
  7668. // Interface : INotifyAppStart
  7669. //
  7670. //--------------------------------------------------------------------------
  7671. HRESULT
  7672. CBaseBrowser2::AppStarted(void)
  7673. {
  7674. _dwStartingAppTick = 0;
  7675. KillTimer( _bbd._hwnd, IDT_STARTING_APP_TIMER );
  7676. SetCursor(LoadCursor(NULL, IDC_ARROW));
  7677. return S_OK;
  7678. }