Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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