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.

4062 lines
125 KiB

  1. #include "priv.h"
  2. #include "sccls.h"
  3. #include "comcat.h"
  4. #include "dvocx.h"
  5. #include <hliface.h>
  6. #include "shlguid.h"
  7. #include "shvocx.h"
  8. #include "winlist.h"
  9. #include <mshtml.h>
  10. #include "stdenum.h"
  11. #include "iface.h"
  12. #include "resource.h"
  13. #include "msiehost.h"
  14. #include <mluisupp.h>
  15. #define SUPERCLASS CShellOcx
  16. #define MIN_HEIGHT 80 // minimum height of a ShellFolderViewOC
  17. #define MIN_WIDTH 80 // minimum width of a ShellFolderViewOC.
  18. #define DEF_WIDTH 300 // default width when we cannot get sizing information
  19. #define DEF_HEIGHT 150 // default height when we cannot get sizing information
  20. #define IPSMSG(psz) TraceMsg(TF_SHDCONTROL, "shv IPS::%s called", (psz))
  21. #define IPSMSG2(psz, hres) TraceMsg(TF_SHDCONTROL, "shv IPS::%s %x", (psz), hres)
  22. #define IPSMSG3(psz, hres, x, y) TraceMsg(TF_SHDCONTROL,"shv IPS::%s %x %d (%d)", (psz), hres, x, y)
  23. #define IOOMSG(psz) TraceMsg(TF_SHDCONTROL, "shv IOO::%s called", (psz))
  24. #define IOOMSG2(psz, i) TraceMsg(TF_SHDCONTROL, "shv IOO::%s called with (%d)", (psz), i)
  25. #define IOOMSG3(psz, i, j) TraceMsg(TF_SHDCONTROL, "shv IOO::%s called with (%d, %d)", (psz), i, j)
  26. #define IVOMSG(psz) TraceMsg(TF_SHDCONTROL, "shv IVO::%s called", (psz))
  27. #define IVOMSG2(psz, i) TraceMsg(TF_SHDCONTROL, "shv IVO::%s called with (%d)", (psz), i)
  28. #define IVOMSG3(psz, i, j) TraceMsg(TF_SHDCONTROL, "shv IVO::%s called with (%d, %d)", (psz), i, j)
  29. #define PROPMSG(psz) TraceMsg(TF_SHDCONTROL, "shv %s", (psz))
  30. #define PROPMSG2(psz, pstr) TraceMsg(TF_SHDCONTROL, "shv %s with [%s]", (psz), pstr)
  31. #define PROPMSG3(psz, hex) TraceMsg(TF_SHDCONTROL, "shv %s with 0x%x", (psz), hex)
  32. #define PRIVMSG(psz) TraceMsg(TF_SHDCONTROL, "shv %s", (psz))
  33. #define CVOCBMSG(psz) TraceMsg(TF_SHDCONTROL, "shv CWebBrowserSB::%s", (psz))
  34. #define IOIPAMSG(psz) TraceMsg(TF_SHDCONTROL, "shv IOIPA::%s", (psz));
  35. #define ABS(i) (((i) < 0) ? -(i) : (i))
  36. #define BOOL_TO_VARIANTBOOL(b) ((b) ? VARIANT_TRUE : VARIANT_FALSE)
  37. #define VARIANTBOOL_TO_BOOL(vb) ((vb == VARIANT_FALSE) ? FALSE : TRUE)
  38. // sizing messages are annoying, but occasionally useful:
  39. #define DM_FORSEARCHBAND 0
  40. static const OLEVERB c_averbsSV[] = {
  41. { 0, (LPWSTR)MAKEINTRESOURCE(IDS_VERB_EDIT), 0, OLEVERBATTRIB_ONCONTAINERMENU },
  42. { 0, NULL, 0, 0 }
  43. };
  44. static const OLEVERB c_averbsDesignSV[] = {
  45. { 0, NULL, 0, 0 }
  46. };
  47. #define HMODULE_NOTLOADED ((HMODULE)-1)
  48. HRESULT TargetQueryService(IUnknown *punk, REFIID riid, void **ppvObj);
  49. /*
  50. * CMsgFilter - implementation of IMessageFilter
  51. *
  52. * Used to reject RPC-reentrant calls while inside AOL
  53. *
  54. */
  55. class CMsgFilter : public IMessageFilter {
  56. public:
  57. // *** IUnknown methods ***
  58. STDMETHODIMP QueryInterface(REFIID riid, void ** ppvObj)
  59. {
  60. // This interface doesn't get QI'ed.
  61. ASSERT(FALSE);
  62. return E_NOINTERFACE;
  63. };
  64. virtual ULONG __stdcall AddRef(void) { return ++_cRef; };
  65. virtual ULONG __stdcall Release(void) { ASSERT(_cRef > 0);
  66. _cRef--;
  67. if (_cRef > 0)
  68. return _cRef;
  69. delete this;
  70. return 0;
  71. };
  72. // *** IMessageFilter specific methods ***
  73. virtual DWORD __stdcall HandleInComingCall(
  74. IN DWORD dwCallType,
  75. IN HTASK htaskCaller,
  76. IN DWORD dwTickCount,
  77. IN LPINTERFACEINFO lpInterfaceInfo)
  78. {
  79. #ifdef DEBUG
  80. WCHAR wszIID[39];
  81. StringFromGUID2( lpInterfaceInfo->iid, wszIID, ARRAYSIZE(wszIID) );
  82. TraceMsg(TF_SHDCONTROL, "shvMF HandleIncomingCall: calltype=%lx, pUnk=%lx, IID=%ws, wMethod=%hu",
  83. dwCallType,
  84. lpInterfaceInfo->pUnk,
  85. wszIID,
  86. lpInterfaceInfo->wMethod);
  87. #endif
  88. //
  89. // The following statement guards against RPC-reentrancy by checking if
  90. // the calltype is TOPLEVEL_CALLPENDING, which means that a call has arrived with a new
  91. // logical threadid and that the object is currently waiting for a reply from a previous
  92. // outgoing call. It's this type of call that has proven troublesome in the past with AOL.
  93. //
  94. // 2-Dec-97: AOL QFE: We need to allow resizing requests to pass through the message filter.
  95. // These appear as IOleObject::SetExtent. Check the IID for IOleObject, and the
  96. // wMethod for 17 (SetExtent is the 17th method in the vtable, Zero-based).
  97. //
  98. const int SetExtent = 17;
  99. if ( ( dwCallType == CALLTYPE_TOPLEVEL_CALLPENDING )
  100. && !(IsEqualIID(lpInterfaceInfo->iid, IID_IOleObject) && lpInterfaceInfo->wMethod == SetExtent) )
  101. {
  102. #ifdef DEBUG
  103. TraceMsg(TF_SHDCONTROL, "shvMF rejected call: calltype=%lx, pUnk=%lx, IID=%ws, wMethod=%hu",
  104. dwCallType,
  105. lpInterfaceInfo->pUnk,
  106. wszIID,
  107. lpInterfaceInfo->wMethod);
  108. #endif
  109. return SERVERCALL_RETRYLATER;
  110. }
  111. if (_lpMFOld)
  112. {
  113. HRESULT hr = _lpMFOld->HandleInComingCall(dwCallType, htaskCaller, dwTickCount, lpInterfaceInfo);
  114. TraceMsg(TF_SHDCONTROL, "shvMF HIC Previous MF returned %x", hr);
  115. return hr;
  116. }
  117. else
  118. {
  119. TraceMsg(TF_SHDCONTROL, "shvMF HIC returning SERVERCALL_ISHANDLED.");
  120. return SERVERCALL_ISHANDLED;
  121. }
  122. };
  123. virtual DWORD __stdcall RetryRejectedCall(
  124. IN HTASK htaskCallee,
  125. IN DWORD dwTickCount,
  126. IN DWORD dwRejectType)
  127. {
  128. TraceMsg(TF_SHDCONTROL, "shv MF RetryRejectedCall htaskCallee=%x, dwTickCount=%x, dwRejectType=%x",
  129. htaskCallee,
  130. dwTickCount,
  131. dwRejectType);
  132. if (_lpMFOld)
  133. {
  134. HRESULT hr = _lpMFOld->RetryRejectedCall(htaskCallee, dwTickCount, dwRejectType);
  135. TraceMsg(TF_SHDCONTROL, "shvMF RRC returned %x", hr);
  136. return hr;
  137. }
  138. else
  139. {
  140. TraceMsg(TF_SHDCONTROL, "shvMF RRC returning 0xffffffff");
  141. return 0xffffffff;
  142. }
  143. };
  144. virtual DWORD __stdcall MessagePending(
  145. IN HTASK htaskCallee,
  146. IN DWORD dwTickCount,
  147. IN DWORD dwPendingType)
  148. {
  149. TraceMsg(TF_SHDCONTROL, "shv MF MessagePending htaskCallee=%x, dwTickCount=%x, dwPendingType=%x",
  150. htaskCallee,
  151. dwTickCount,
  152. dwPendingType);
  153. if (_lpMFOld)
  154. {
  155. HRESULT hr = _lpMFOld->MessagePending(htaskCallee, dwTickCount, dwPendingType);
  156. TraceMsg(TF_SHDCONTROL, "shvMF RRC returned %x", hr);
  157. return hr;
  158. }
  159. else
  160. {
  161. TraceMsg(TF_SHDCONTROL, "shvMF MP returning PENDINGMSG_WAITDEFPROCESS");
  162. return PENDINGMSG_WAITDEFPROCESS;
  163. }
  164. };
  165. CMsgFilter() : _cRef(1)
  166. {
  167. ASSERT(_lpMFOld == NULL);
  168. };
  169. BOOL Initialize()
  170. {
  171. BOOL bResult = CoRegisterMessageFilter((LPMESSAGEFILTER)this, &_lpMFOld) != S_FALSE;
  172. TraceMsg(TF_SHDCONTROL, "shv Previous message filter is %lx", _lpMFOld);
  173. return bResult;
  174. };
  175. void UnInitialize()
  176. {
  177. TraceMsg(TF_SHDCONTROL, "shv MF Uninitializing, previous message filter = %x", _lpMFOld);
  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. CWebBrowserOC::CWebBrowserOC(IUnknown* punkOuter, LPCOBJECTINFO poi) :
  189. SUPERCLASS(punkOuter, poi, c_averbsSV, c_averbsDesignSV)
  190. {
  191. TraceMsg(TF_SHDLIFE, "ctor CWebBrowserOC %x", this);
  192. // flag special so we only try to load browseui once
  193. _hBrowseUI = HMODULE_NOTLOADED;
  194. }
  195. BOOL CWebBrowserOC::_InitializeOC(IUnknown *punkOuter)
  196. {
  197. // we used a zero-init memory allocator, so everything else is NULL.
  198. // check to be sure:
  199. ASSERT(!_fInit);
  200. // By default, we're visible. Everything else can default to FALSE.
  201. //
  202. _fVisible = 1;
  203. // CShellOcx holds the default event source which is DIID_DWebBrowserEvents2
  204. m_cpWB1Events.SetOwner(_GetInner(), &DIID_DWebBrowserEvents);
  205. // some stuff we want to set up now. we're a WebBrowser, so create the
  206. // IShellBrowser now. We need an aggregated automation object before
  207. // we do that.
  208. CIEFrameAuto_CreateInstance(SAFECAST(this, IOleControl*), &_pauto);
  209. if (_pauto)
  210. {
  211. // Cache some interfaces of CIEFrameAuto.
  212. //
  213. // Since we aggregate CIEFrameAuto, this will increase our refcount.
  214. // We cannot release this interface and expect it to work, so we
  215. // call release on ourself to remove the refcount cycle.
  216. //
  217. // Since we ourselves may be aggregated and we always want to get
  218. // CIEFrameAuto's interface and not our aggregator's, we delay
  219. // setting up punkOuter until below.
  220. //
  221. _pauto->QueryInterface(IID_PPV_ARG(IWebBrowser2, &_pautoWB2));
  222. ASSERT(_pautoWB2);
  223. Release();
  224. _pauto->QueryInterface(IID_PPV_ARG(IExpDispSupport, &_pautoEDS));
  225. ASSERT(_pautoEDS);
  226. Release();
  227. }
  228. // Now set up our aggregator's punkOuter
  229. if (punkOuter)
  230. {
  231. CAggregatedUnknown::_SetOuter(punkOuter);
  232. }
  233. // postpone initialization of stuff that may be persisted
  234. // until InitNew is called.
  235. // Were we successful? (we don't have to free this
  236. // here on failure, cuz we'll free them on delete)
  237. return (NULL!=_pauto);
  238. }
  239. CWebBrowserOC::~CWebBrowserOC()
  240. {
  241. TraceMsg(TF_SHDLIFE, "dtor CWebBrowserOC %x", this);
  242. ASSERT(!_fDidRegisterAsBrowser);
  243. _UnregisterWindow(); // Last Chance - should have been done in InplaceDeactivate
  244. if (_psb) {
  245. ATOMICRELEASET(_psb, CWebBrowserSB);
  246. }
  247. ATOMICRELEASE(_plinkA);
  248. // We need to release these cached interface pointers.
  249. //
  250. // Since we cached them before setting up our outer-aggregation,
  251. // we need to un-outer-aggregate ourself first.
  252. //
  253. // Since we aggregate CIEFrameAuto (where these come from) we need
  254. // to AddRef ourself before releasing. Fortunately, this is done for us
  255. // by CAggregatedUnknown::Release (it bumps _cRef to 1000).
  256. //
  257. CAggregatedUnknown::_SetOuter(CAggregatedUnknown::_GetInner());
  258. ATOMICRELEASE(_pautoWB2);
  259. ATOMICRELEASE(_pautoEDS);
  260. ATOMICRELEASE(_pauto);
  261. if (_hmemSB) {
  262. GlobalFree(_hmemSB);
  263. _hmemSB = NULL;
  264. }
  265. if (_hBrowseUI != 0 && _hBrowseUI != HMODULE_NOTLOADED)
  266. FreeLibrary(_hBrowseUI);
  267. }
  268. IStream *CWebBrowserSB::v_GetViewStream(LPCITEMIDLIST pidl, DWORD grfMode, LPCWSTR pwszName)
  269. {
  270. TCHAR szName[MAX_PATH];
  271. SHUnicodeToTChar(pwszName, szName, ARRAYSIZE(szName));
  272. return GetViewStream(pidl, grfMode, szName, REGSTR_PATH_EXPLORER TEXT("\\OCXStreamMRU"), TEXT("OCXStreams"));
  273. }
  274. void CWebBrowserOC::_InitDefault()
  275. {
  276. if (_fInit)
  277. {
  278. IPSMSG(TEXT("_InitDefault already initialized"));
  279. return;
  280. }
  281. _fInit = TRUE;
  282. // Different versions of the control get different defaults.
  283. if (_pObjectInfo->lVersion == VERSION_1)
  284. {
  285. // AOL 3.0 compatibility: register as a browser window on InPlaceActivate
  286. _fShouldRegisterAsBrowser = TRUE;
  287. }
  288. else
  289. {
  290. // we use a zero-init memory allocator, so everything else is NULL.
  291. ASSERT(FALSE == _fShouldRegisterAsBrowser);
  292. }
  293. _size.cx = DEF_WIDTH;
  294. _size.cy = DEF_HEIGHT;
  295. _sizeHIM = _size;
  296. PixelsToMetric(&_sizeHIM);
  297. _fs.ViewMode = FVM_ICON;
  298. _fs.fFlags = FWF_AUTOARRANGE | FWF_NOCLIENTEDGE;
  299. }
  300. void CWebBrowserOC::_RegisterWindow()
  301. {
  302. if (!_fDidRegisterAsBrowser && _pipsite && _fShouldRegisterAsBrowser)
  303. {
  304. ITargetFrame2 *ptgf;
  305. HRESULT hr;
  306. if (SUCCEEDED(QueryInterface(IID_PPV_ARG(ITargetFrame2, &ptgf))))
  307. {
  308. IUnknown *pUnkParent;
  309. hr = ptgf->GetParentFrame(&pUnkParent);
  310. if (SUCCEEDED(hr) && pUnkParent != NULL)
  311. {
  312. pUnkParent->Release();
  313. }
  314. else
  315. {
  316. IShellWindows* psw = WinList_GetShellWindows(TRUE);
  317. if (psw)
  318. {
  319. IDispatch* pid;
  320. if (SUCCEEDED(ptgf->QueryInterface(IID_PPV_ARG(IDispatch, &pid))))
  321. {
  322. psw->Register(pid, PtrToLong(_hwnd), SWC_3RDPARTY, &_cbCookie);
  323. _fDidRegisterAsBrowser = 1;
  324. pid->Release();
  325. }
  326. psw->Release();
  327. }
  328. }
  329. ptgf->Release();
  330. }
  331. }
  332. }
  333. void CWebBrowserOC::_UnregisterWindow()
  334. {
  335. if (_fDidRegisterAsBrowser)
  336. {
  337. IShellWindows* psw = NULL;
  338. psw = WinList_GetShellWindows(TRUE);
  339. if (psw)
  340. {
  341. psw->Revoke(_cbCookie);
  342. _fDidRegisterAsBrowser = 0;
  343. psw->Release();
  344. }
  345. }
  346. }
  347. HRESULT CWebBrowserOC::Draw(
  348. DWORD dwDrawAspect,
  349. LONG lindex,
  350. void *pvAspect,
  351. DVTARGETDEVICE *ptd,
  352. HDC hdcTargetDev,
  353. HDC hdcDraw,
  354. LPCRECTL lprcBounds,
  355. LPCRECTL lprcWBounds,
  356. BOOL ( __stdcall *pfnContinue )(ULONG_PTR dwContinue),
  357. ULONG_PTR dwContinue)
  358. {
  359. IS_INITIALIZED;
  360. HRESULT hres;
  361. IVOMSG3(TEXT("Draw called"), lprcBounds->top, lprcBounds->bottom);
  362. IViewObject *pvo;
  363. if (_psb && _psb->GetShellView() &&
  364. SUCCEEDED(_psb->GetShellView()->QueryInterface(IID_PPV_ARG(IViewObject, &pvo))))
  365. {
  366. hres = pvo->Draw(dwDrawAspect, lindex, pvAspect, ptd, hdcTargetDev, hdcDraw,
  367. lprcBounds, lprcWBounds, pfnContinue, dwContinue);
  368. pvo->Release();
  369. if (SUCCEEDED(hres))
  370. return hres;
  371. }
  372. // If we don't have a shell view, or if it couldn't draw, then we draw ourselves.
  373. // (if we're in design mode).
  374. //
  375. if (_IsDesignMode())
  376. {
  377. FillRect(hdcDraw, (RECT*) lprcBounds, (HBRUSH)GetStockObject(BLACK_BRUSH));
  378. SIZE size = { ABS( lprcBounds->right - lprcBounds->left ),
  379. ABS( lprcBounds->bottom - lprcBounds->top ) };
  380. HBITMAP hImage;
  381. HDC hdcTmp = CreateCompatibleDC( hdcDraw );
  382. HMODULE hBrowseUI;
  383. hBrowseUI = _GetBrowseUI();
  384. if ( hBrowseUI )
  385. hImage = LoadBitmap( hBrowseUI, MAKEINTRESOURCE( IDB_IEBRAND ));
  386. else
  387. hImage = NULL;
  388. // hdcDraw may be a metafile, in which case the CreateCompatibleDC call will fail.
  389. //
  390. if ( !hdcTmp )
  391. {
  392. hdcTmp = CreateCompatibleDC( hdcTargetDev ); // Okay if hdcTargetDev == NULL
  393. }
  394. if (hdcTmp)
  395. {
  396. if ( hImage )
  397. {
  398. BITMAP bm;
  399. POINT ptOriginDest; // origin of destination
  400. SIZE sizeDest;
  401. POINT ptOriginSrc = { 0, 0 };
  402. SIZE sizeSrc;
  403. GetObject( hImage, sizeof( bm ), &bm );
  404. HGDIOBJ hPrev = SelectObject( hdcTmp, hImage );
  405. // Yes, this looks wrong, but it's right. We only want the first frame
  406. // of the brand bitmap, and the frames are stacked vertically.
  407. //
  408. sizeSrc.cx = sizeSrc.cy = bm.bmWidth;
  409. // This code centers the bitmap while preserving its aspect ratio.
  410. //
  411. if ( size.cx > size.cy )
  412. {
  413. // if destination is wider than tall,
  414. //
  415. ptOriginDest.x = lprcBounds->left + size.cx/2 - size.cy/2;
  416. ptOriginDest.y = lprcBounds->top;
  417. sizeDest.cx = size.cy;
  418. sizeDest.cy = lprcBounds->bottom - lprcBounds->top >= 0 ? size.cy : -size.cy;
  419. }
  420. else
  421. {
  422. // else destination is taller than wide
  423. //
  424. ptOriginDest.x = lprcBounds->left;
  425. ptOriginDest.y = lprcBounds->bottom - lprcBounds->top >= 0
  426. ? ( lprcBounds->top + size.cy/2 - size.cx/2 )
  427. : -( lprcBounds->top + size.cy/2 - size.cx/2 );
  428. sizeDest.cx = size.cx;
  429. sizeDest.cy = lprcBounds->bottom - lprcBounds->top >= 0 ? size.cx : -size.cx;
  430. }
  431. StretchBlt( hdcDraw,
  432. ptOriginDest.x, ptOriginDest.y,
  433. sizeDest.cx, sizeDest.cy,
  434. hdcTmp,
  435. ptOriginSrc.x, ptOriginSrc.y,
  436. sizeSrc.cx, sizeSrc.cy,
  437. SRCCOPY );
  438. SelectObject( hdcTmp, hPrev );
  439. DeleteObject( hImage );
  440. }
  441. DeleteDC( hdcTmp );
  442. }
  443. return S_OK;
  444. }
  445. return SUPERCLASS::Draw(dwDrawAspect, lindex, pvAspect, ptd, hdcTargetDev, hdcDraw,
  446. lprcBounds, lprcWBounds, pfnContinue, dwContinue);
  447. }
  448. HRESULT CWebBrowserOC::GetColorSet(DWORD dwAspect, LONG lindex,
  449. void *pvAspect, DVTARGETDEVICE *ptd, HDC hicTargetDev,
  450. LOGPALETTE **ppColorSet)
  451. {
  452. IViewObject *pvo;
  453. if (_psb && _psb->GetShellView() &&
  454. SUCCEEDED(_psb->GetShellView()->QueryInterface(IID_PPV_ARG(IViewObject, &pvo))))
  455. {
  456. HRESULT hres = pvo->GetColorSet(dwAspect, lindex, pvAspect, ptd,
  457. hicTargetDev, ppColorSet);
  458. pvo->Release();
  459. if (SUCCEEDED(hres))
  460. return hres;
  461. }
  462. return SUPERCLASS::GetColorSet(dwAspect, lindex, pvAspect, ptd,
  463. hicTargetDev, ppColorSet);
  464. }
  465. HRESULT CWebBrowserOC::SetExtent(DWORD dwDrawAspect, SIZEL *psizel)
  466. {
  467. HRESULT hr = SUPERCLASS::SetExtent(dwDrawAspect, psizel);
  468. if ( FAILED( hr ))
  469. {
  470. return hr;
  471. }
  472. //
  473. // If oc < inplace then forward SetExtent through to docobject.
  474. // If docobject is already inplace active, SetExtent is meaningless.
  475. //
  476. if (_nActivate < OC_INPLACEACTIVE)
  477. {
  478. IPrivateOleObject * pPrivOle = NULL;
  479. if ( _psb && _psb->GetShellView() &&
  480. SUCCEEDED(_psb->GetShellView()->QueryInterface(IID_PPV_ARG(IPrivateOleObject, &pPrivOle))))
  481. {
  482. // we have an ole object, delegate downwards...
  483. hr = pPrivOle->SetExtent( dwDrawAspect, psizel );
  484. pPrivOle->Release();
  485. }
  486. _dwDrawAspect = dwDrawAspect;
  487. // the size is already cached in _sizeHIM in our base class by the SUPERCLASS::SetExtent()
  488. }
  489. return hr;
  490. }
  491. // Called after the client site has been set so we can process
  492. // stuff in the correct order
  493. //
  494. void CWebBrowserOC::_OnSetClientSite()
  495. {
  496. // Until we have a client site we can't determine toplevelness.
  497. //
  498. if (_pcli)
  499. {
  500. BOOL fFoundBrowserService = FALSE;
  501. IBrowserService *pbsTop;
  502. if (SUCCEEDED(IUnknown_QueryService(_pcli, SID_STopLevelBrowser, IID_PPV_ARG(IBrowserService, &pbsTop))))
  503. {
  504. fFoundBrowserService = TRUE;
  505. pbsTop->Release();
  506. }
  507. // if nobody above us supports IBrowserService, we must be toplevel.
  508. if (!fFoundBrowserService)
  509. _fTopLevel = TRUE;
  510. // If we haven't created CWebBrowserSB, do so now.
  511. // We do this before our superclass OnSetClientSite
  512. // because shembed will create the window which
  513. // requires _psb's existence.
  514. //
  515. // NOTE: We do this here instead of _Initialize because
  516. // CBaseBrowser will QI us for interfaces during this call.
  517. // If we're in the middle of our CreateInstance function
  518. // and we've been aggregated, we pass the QI to _punkAgg
  519. // who faults because we haven't returned from CoCreateInstance.
  520. //
  521. // NOTE: We now destroy our window on SetClientSite(NULL)
  522. // which frees ths _psb, so we should create this every time.
  523. //
  524. if (!_psb)
  525. {
  526. // Give _psb our inner unknown so we never get interfaces
  527. // from whoever may aggregate us. _GetInner gives us
  528. // first crack at QueryInterface so we get the correct
  529. // IWebBrowser implementation.
  530. //
  531. _psb = new CWebBrowserSB(CAggregatedUnknown::_GetInner(), this);
  532. // if we don't get _psb we're totally hosed...
  533. //
  534. if (_psb)
  535. {
  536. _psb->_fldBase._fld._fs = _fs;
  537. // tell _psb if it's top-level or not
  538. //
  539. if (_fTopLevel)
  540. {
  541. _psb->SetTopBrowser();
  542. }
  543. // CBaseBrowser assumes SVUIA_ACTIVATE_FOCUS, tell it what we really are
  544. //
  545. ASSERT(OC_DEACTIVE == _nActivate); // we shouldn't be activated yet
  546. _psb->_UIActivateView(SVUIA_DEACTIVATE);
  547. }
  548. else
  549. {
  550. TraceMsg(TF_WARNING, "Couldn't create _psb. We are hosed!");
  551. // don't let the window get created by our superclass,
  552. // as we can't do anything anyway...
  553. //
  554. return;
  555. }
  556. }
  557. }
  558. else
  559. {
  560. // Tell our aggregatee that their cached window is invalid
  561. //
  562. IEFrameAuto * piefa;
  563. if (EVAL(SUCCEEDED(_pauto->QueryInterface(IID_PPV_ARG(IEFrameAuto, &piefa)))))
  564. {
  565. piefa->SetOwnerHwnd(NULL);
  566. piefa->Release();
  567. }
  568. if (_lpMF)
  569. {
  570. IMessageFilter* lpMF = _lpMF;
  571. _lpMF = NULL;
  572. ((CMsgFilter *)lpMF)->UnInitialize();
  573. EVAL(lpMF->Release() == 0);
  574. }
  575. // Decrement the browser session count
  576. //
  577. if (_fIncrementedSessionCount)
  578. {
  579. SetQueryNetSessionCount(SESSION_DECREMENT);
  580. _fIncrementedSessionCount = FALSE; // In case this instance is reused.
  581. }
  582. }
  583. SUPERCLASS::_OnSetClientSite();
  584. if (_pcli)
  585. {
  586. VARIANT_BOOL fAmbient = VARIANT_FALSE;
  587. HWND hwndParent = NULL;
  588. // We init the local properties using ambients if available
  589. // If this fails, fAmbient will be left at VARIANT_FALSE which is what we need for the next
  590. // statement.
  591. //
  592. if (SUPERCLASS::_GetAmbientProperty(DISPID_AMBIENT_OFFLINEIFNOTCONNECTED, VT_BOOL, &fAmbient))
  593. {
  594. put_Offline(fAmbient);
  595. }
  596. // If top-level and not offline, increment the browser session count.
  597. //
  598. if (_fTopLevel && !fAmbient)
  599. {
  600. SetQueryNetSessionCount(SESSION_INCREMENT_NODEFAULTBROWSERCHECK);
  601. _fIncrementedSessionCount = TRUE;
  602. }
  603. if (SUPERCLASS::_GetAmbientProperty(DISPID_AMBIENT_SILENT, VT_BOOL, &fAmbient))
  604. {
  605. put_Silent(fAmbient);
  606. }
  607. // After the parent window has been set, check to see if it is on the same thread as us.
  608. // If not, we have a cross-thread container and we need a message filter.
  609. //
  610. if ( _fTopLevel // If we're top level
  611. && _hwnd // and we have an hwnd (we should)
  612. && (hwndParent = GetParent( _hwnd ) ) // and we have a parent window
  613. // and the parent window is on a different thread
  614. && GetWindowThreadProcessId( _hwnd, NULL ) != GetWindowThreadProcessId( hwndParent, NULL ))
  615. {
  616. if (!_lpMF)
  617. {
  618. /*
  619. * Create a message filter here to reject RPC-reentrant calls.
  620. */
  621. _lpMF = new CMsgFilter();
  622. if (_lpMF && !(((CMsgFilter *)_lpMF)->Initialize()))
  623. {
  624. ATOMICRELEASE(_lpMF);
  625. }
  626. TraceMsg(TF_SHDCONTROL, "shv Registering message filter (%lx) for RPC-reentrancy", _lpMF);
  627. }
  628. }
  629. // if we have a pending navigation from IPS::Load, do it now.
  630. //
  631. if (_fNavigateOnSetClientSite && _plinkA && _psb)
  632. {
  633. //
  634. // We hit this code if this OC is IPersistStream::Loaded before
  635. // the client site is set.
  636. //
  637. LPITEMIDLIST pidl;
  638. if (SUCCEEDED(_plinkA->GetIDList(&pidl)) && pidl)
  639. {
  640. _BrowseObject(pidl);
  641. ILFree(pidl);
  642. }
  643. _fNavigateOnSetClientSite = FALSE;
  644. }
  645. }
  646. }
  647. STDAPI CWebBrowserOC_CreateInstance(IUnknown* punkOuter, IUnknown** ppunk, LPCOBJECTINFO poi)
  648. {
  649. HRESULT hres;
  650. hres = E_OUTOFMEMORY;
  651. CWebBrowserOC* psvo = new CWebBrowserOC(NULL, poi);
  652. if (psvo)
  653. {
  654. if (!psvo->_InitializeOC(punkOuter))
  655. {
  656. psvo->Release();
  657. }
  658. else
  659. {
  660. *ppunk = psvo->_GetInner();
  661. hres = S_OK;
  662. }
  663. }
  664. return hres;
  665. }
  666. LRESULT CWebBrowserOC::_OnPaintPrint(HDC hdcPrint)
  667. {
  668. PAINTSTRUCT ps;
  669. HDC hdc = hdcPrint ? hdcPrint : BeginPaint(_hwnd, &ps);
  670. RECT rc;
  671. GetClientRect(_hwnd, &rc);
  672. DrawEdge(hdc, &rc, EDGE_SUNKEN, BF_ADJUST|BF_RECT|BF_SOFT);
  673. DrawText(hdc, hdcPrint ? TEXT("Print") : TEXT("Paint"),
  674. -1, &rc, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
  675. if (!hdcPrint)
  676. {
  677. EndPaint(_hwnd, &ps);
  678. }
  679. return 0;
  680. }
  681. HRESULT CWebBrowserOC::_BrowseObject(LPCITEMIDLIST pidlBrowseTo)
  682. {
  683. if (_psb)
  684. return _psb->BrowseObject(pidlBrowseTo, SBSP_SAMEBROWSER | SBSP_ABSOLUTE);
  685. // if no _psb at this point, container did not
  686. // honor OLEMISC_SETCLIENTSITEFIRST bit, so silently
  687. // fail instead of trying to make this work
  688. ASSERT(FALSE);
  689. return E_FAIL;
  690. }
  691. LRESULT CWebBrowserOC::_OnCreate(LPCREATESTRUCT lpcs)
  692. {
  693. LRESULT lres;
  694. if (_psb)
  695. {
  696. ASSERT(_hwnd);
  697. _psb->_SetWindow(_hwnd);
  698. lres = _psb->OnCreate(NULL);
  699. }
  700. else
  701. {
  702. lres = (LRESULT)-1;
  703. }
  704. //
  705. // If IPersistStream::Load has stored away a block of stream for
  706. // toolbars, this is the time to use it.
  707. //
  708. if (_hmemSB)
  709. {
  710. #if 0
  711. // only do the load if we're successfully creating the window
  712. if (lres != -1)
  713. {
  714. IStream* pstm;
  715. HRESULT hresT = ::CreateStreamOnHGlobal(_hmemSB, FALSE, &pstm);
  716. if (SUCCEEDED(hresT))
  717. {
  718. _psb->_LoadToolbars(pstm);
  719. pstm->Release();
  720. }
  721. }
  722. #endif
  723. GlobalFree(_hmemSB);
  724. _hmemSB = NULL;
  725. }
  726. return lres;
  727. }
  728. //
  729. // This is a virtual function defined in CShellEmbedding class, which
  730. // is called when all but WM_NCCREATE and WM_NCDESTROY messages are
  731. // dispatched to the our "Shell Embedding" window. It's important
  732. // to remember that we pass this window handle to the constructor of
  733. // CWebBrowserSB (which calls the constructor of CBaseBrowser).
  734. // That's why we forward all messages to _psb->WndProcBS. (SatoNa)
  735. //
  736. LRESULT CWebBrowserOC::v_WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  737. {
  738. LRESULT lres = 0L;
  739. if (WM_CREATE == uMsg)
  740. {
  741. // We need first crack at this message before
  742. // forwarding it along to _psb (which we do
  743. // in this _OnCreate call)
  744. return _OnCreate((LPCREATESTRUCT)lParam);
  745. }
  746. // only let _psb look at it if the message is not reserved for us
  747. if (!IsInRange(uMsg, CWM_RESERVEDFORWEBBROWSER_FIRST, CWM_RESERVEDFORWEBBROWSER_LAST))
  748. {
  749. BOOL fDontForward = FALSE;
  750. // destroy bottom up for these
  751. switch (uMsg)
  752. {
  753. case WM_DESTROY:
  754. case WM_CLOSE:
  755. SUPERCLASS::v_WndProc(hwnd, uMsg, wParam, lParam);
  756. fDontForward = TRUE;
  757. break;
  758. }
  759. //
  760. // This AssertMsg will help debugging IE v4.1 bug 12931.
  761. //
  762. // Comment out assert now that we don't create _psb at constructor time. (?)
  763. //AssertMsg((BOOL)_psb, "WBOC::v_WndProc _psb==NULL! uMsg=%x", uMsg);
  764. if (_psb)
  765. {
  766. lres = _psb->WndProcBS(hwnd, uMsg, wParam, lParam);
  767. // Due to aggregation of IEFrameAuto, _psb is holding references
  768. // to us, so we need to break the cycle.
  769. // _psb may have been freed above. Double check it.
  770. //
  771. if (uMsg == WM_DESTROY && _psb)
  772. {
  773. _psb->ReleaseShellView();
  774. _psb->ReleaseShellExplorer();
  775. ATOMICRELEASET(_psb, CWebBrowserSB);
  776. }
  777. }
  778. if (uMsg >= WM_USER || fDontForward)
  779. {
  780. return lres;
  781. }
  782. }
  783. switch(uMsg)
  784. {
  785. /* these are handled by CBaseBrowser only */
  786. case WM_NOTIFY:
  787. return lres;
  788. case WM_SETCURSOR:
  789. if (lres) {
  790. return lres;
  791. }
  792. goto DoDefault;
  793. DoDefault:
  794. default:
  795. return SUPERCLASS::v_WndProc(hwnd, uMsg, wParam, lParam);
  796. }
  797. return 0L;
  798. }
  799. HRESULT CWebBrowserOC::Close(DWORD dwSaveOption)
  800. {
  801. if (_psb)
  802. {
  803. _psb->_CancelPendingNavigation();
  804. }
  805. if (_pauto)
  806. {
  807. IWebBrowserPriv * pWBPriv;
  808. HRESULT hr = _pauto->QueryInterface(IID_IWebBrowserPriv, (void**)&pWBPriv);
  809. if (SUCCEEDED(hr))
  810. {
  811. pWBPriv->OnClose();
  812. pWBPriv->Release();
  813. }
  814. }
  815. return SUPERCLASS::Close(dwSaveOption);
  816. }
  817. HRESULT CWebBrowserOC::SetHostNames(LPCOLESTR szContainerApp, LPCOLESTR szContainerObj)
  818. {
  819. IOOMSG(TEXT("SetHostNames"));
  820. // We are not interested in host name
  821. // ...well ... maybe a little. this turns out to be the best place to
  822. // do an apphack for VC 5.0. VC 5.0 has a bug where it calls Release()
  823. // one too many times. the only good way to detect being hosted in the
  824. // offending container is to check the szContainerApp in SetHostNames!
  825. // ...chrisfra 8/14/97, bug 30428
  826. // NOTE: Mike Colee of VC verified their bug and will put a Raid bug in
  827. // their database including how to signal that a new version works by
  828. // changing szContainerApp string.
  829. if (_fTopLevel && szContainerApp && !StrCmpW(szContainerApp, L"DevIV Package"))
  830. {
  831. AddRef();
  832. }
  833. return SUPERCLASS::SetHostNames(szContainerApp, szContainerObj);
  834. }
  835. HRESULT CWebBrowserOC::DoVerb(
  836. LONG iVerb,
  837. LPMSG lpmsg,
  838. IOleClientSite *pActiveSite,
  839. LONG lindex,
  840. HWND hwndParent,
  841. LPCRECT lprcPosRect)
  842. {
  843. IS_INITIALIZED;
  844. _pmsgDoVerb = lpmsg;
  845. HRESULT hr = SUPERCLASS::DoVerb(iVerb, lpmsg, pActiveSite, lindex, hwndParent, lprcPosRect);
  846. _pmsgDoVerb = NULL;
  847. return hr;
  848. }
  849. // *** IPersistStreamInit ***
  850. // in order to have upgrade and downgrade compatibility in stream formats
  851. // we can't have any size assumptions in this code. Extra data streamed
  852. // after our PersistSVOCX structure must be referenced by a dwOffX offset
  853. // so the downgrade case knows where to start reading from.
  854. //
  855. // since we always write out a stream that's downward compatible, we don't
  856. // need to folow the "source compatible" rule of: reading an old stream
  857. // with an old CLSID WebBrowser implies that when we save, we need to
  858. // save using the old stream format.
  859. //
  860. typedef struct _PersistSVOCX
  861. {
  862. struct _tagIE30 {
  863. DWORD cbSize;
  864. SIZE sizeObject; // IE3 saves as PIXELS, IE4 saves as HIMETRIC
  865. FOLDERSETTINGS fs;
  866. long lAutoSize; // IE3, no longer used
  867. DWORD fColorsSet; // IE3, no longer used
  868. COLORREF clrBack; // IE3, no longer used
  869. COLORREF clrFore; // IE3, no longer used
  870. DWORD dwOffPersistLink;
  871. long lAutoSizePercentage; // IE3, no longer used
  872. } ie30;
  873. struct _tagIE40 {
  874. DWORD dwExtra;
  875. BOOL bRestoreView;
  876. SHELLVIEWID vid;
  877. DWORD fFlags;
  878. DWORD dwVersion;
  879. } ie40;
  880. } PersistSVOCX;
  881. //
  882. // Flags for dwExtra. Having a flag indicate that we have some extra
  883. // streamed data after this structure + persisted link.
  884. //
  885. // NOTE: All data stored this way (instead of storing an offset to
  886. // the data, such as dwOffPersistLink) will be lost on downgrade
  887. // cases and cases where we have to emulate old stream formats.
  888. //
  889. #define SVO_EXTRA_TOOLBARS 0x00000001
  890. // Random flags we need to persist
  891. #define SVO_FLAGS_OFFLINE 0x00000001
  892. #define SVO_FLAGS_SILENT 0x00000002
  893. #define SVO_FLAGS_REGISTERASBROWSER 0x00000004
  894. #define SVO_FLAGS_REGISTERASDROPTGT 0x00000008
  895. #define SVO_VERSION 0 // increment for upgrade changes when size doesn't change
  896. HRESULT CWebBrowserOC::Load(IStream *pstm)
  897. {
  898. IPSMSG(TEXT("Load"));
  899. // Load _size
  900. ULONG cbRead;
  901. PersistSVOCX sPersist;
  902. HRESULT hres, hresNavigate = E_FAIL;
  903. DWORD dwExtra = 0;
  904. // It is illegal to call Load or InitNew more than once
  905. if (_fInit)
  906. {
  907. TraceMsg(TF_SHDCONTROL, "shv IPersistStream::Load called when ALREADY INITIALIZED!");
  908. ASSERT(FALSE);
  909. return E_FAIL;
  910. }
  911. // we need an IShellLink to read into
  912. if (_plinkA == NULL)
  913. {
  914. hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IShellLinkA, &_plinkA));
  915. if (FAILED(hres))
  916. return hres;
  917. }
  918. // remember our starting location
  919. ULARGE_INTEGER liStart;
  920. //ULARGE_INTEGER liEnd;
  921. LARGE_INTEGER liMove;
  922. liMove.LowPart = liMove.HighPart = 0;
  923. hres = pstm->Seek(liMove, STREAM_SEEK_CUR, &liStart);
  924. if (FAILED(hres))
  925. {
  926. return hres;
  927. }
  928. // Zero initialize our struct
  929. ZeroMemory(&sPersist, SIZEOF(sPersist));
  930. hres = pstm->Read(&sPersist, SIZEOF(DWORD), &cbRead);
  931. if (SUCCEEDED(hres))
  932. {
  933. // Validate the data
  934. if (cbRead != SIZEOF(DWORD) ||
  935. sPersist.ie30.cbSize < SIZEOF(sPersist.ie30))
  936. {
  937. TraceMsg(DM_ERROR, "Someone is asking us to read the wrong thing.");
  938. hres = E_FAIL;
  939. }
  940. else
  941. {
  942. DWORD cbSizeToRead = sPersist.ie30.cbSize;
  943. if (cbSizeToRead > SIZEOF(sPersist))
  944. {
  945. // must be a newer struct, only read what we know (ie, don't trash the stack!)
  946. cbSizeToRead = SIZEOF(sPersist);
  947. }
  948. cbSizeToRead -= SIZEOF(DWORD); // remove what we've already read
  949. hres = pstm->Read(&sPersist.ie30.sizeObject, cbSizeToRead, &cbRead);
  950. if (SUCCEEDED(hres))
  951. {
  952. if (cbRead != cbSizeToRead)
  953. {
  954. hres = E_FAIL;
  955. }
  956. else
  957. {
  958. // read ie30 data
  959. //
  960. if (EVAL(sPersist.ie30.cbSize >= SIZEOF(sPersist.ie30)))
  961. {
  962. _size = sPersist.ie30.sizeObject;
  963. _fs = sPersist.ie30.fs;
  964. // IE3 saved size in pixels IE4 saves size in HIM already
  965. //
  966. _sizeHIM = _size;
  967. if (sPersist.ie30.cbSize == SIZEOF(sPersist.ie30) ||
  968. sPersist.ie30.cbSize == SIZEOF(sPersist) - SIZEOF(sPersist.ie40.dwVersion)) // handle upgrade
  969. {
  970. // Size is in pixels. Adjust _sizeHIM to Hi Metric.
  971. PixelsToMetric(&_sizeHIM);
  972. }
  973. else
  974. {
  975. // Size is in Hi Metric. Adjust _size to Pixels.
  976. MetricToPixels(&_size);
  977. }
  978. if (_psb) // if no _psb then container ignored OLEMISC_SETCLIENTSITEFIRST
  979. _psb->_fldBase._fld._fs = _fs;
  980. // Load _plinkA
  981. IPersistStream* ppstm;
  982. hres = _plinkA->QueryInterface(IID_PPV_ARG(IPersistStream, &ppstm));
  983. if (SUCCEEDED(hres))
  984. {
  985. ASSERT(sPersist.ie30.dwOffPersistLink >= sPersist.ie30.cbSize);
  986. liMove.LowPart = liStart.LowPart + sPersist.ie30.dwOffPersistLink;
  987. hres = pstm->Seek(liMove, STREAM_SEEK_SET, NULL);
  988. if (SUCCEEDED(hres))
  989. {
  990. hres = ppstm->Load(pstm);
  991. if (SUCCEEDED(hres))
  992. {
  993. // We always save link info last,
  994. // so remember where we are in the stream.
  995. // Since we don't have more dwOff variables
  996. // currently, don't bother remebering this...
  997. //hres = pstm->Seek(liMove, STREAM_SEEK_CUR, &liEnd);
  998. //if (SUCCEEDED(hres))
  999. _fInit = TRUE;
  1000. // in case the target moved invoke link tracking (ignore errors)
  1001. _plinkA->Resolve(_hwnd, SLR_NO_UI);
  1002. // If we already have the client site,
  1003. // navigate now. Otherwise, navigate
  1004. // when the client site is set.
  1005. if (_pcli)
  1006. {
  1007. LPITEMIDLIST pidl;
  1008. if (SUCCEEDED(_plinkA->GetIDList(&pidl)) && pidl)
  1009. {
  1010. ASSERT(FALSE == _psb->_fAsyncNavigate);
  1011. _psb->_fAsyncNavigate = TRUE;
  1012. hresNavigate = _BrowseObject(pidl);
  1013. _psb->_fAsyncNavigate = FALSE;
  1014. ILFree(pidl);
  1015. }
  1016. }
  1017. else
  1018. {
  1019. _fNavigateOnSetClientSite = TRUE;
  1020. }
  1021. }
  1022. }
  1023. ppstm->Release();
  1024. }
  1025. } // read ie30 data
  1026. // temp upgrade hack for older struct
  1027. if (sPersist.ie30.cbSize == SIZEOF(sPersist) - SIZEOF(sPersist.ie40.dwVersion))
  1028. {
  1029. // dwVersion field is already correct, update cbSize
  1030. // to pass below size check
  1031. sPersist.ie30.cbSize = SIZEOF(sPersist);
  1032. }
  1033. // read ie40 data
  1034. if (SUCCEEDED(hres) &&
  1035. sPersist.ie30.cbSize >= SIZEOF(sPersist))
  1036. {
  1037. if (_psb) // if no _psb then container ignored OLEMISC_SETCLIENTSITEFIRST
  1038. {
  1039. if (sPersist.ie40.bRestoreView)
  1040. {
  1041. _psb->_fldBase._fld._vidRestore = sPersist.ie40.vid;
  1042. // since we read the ie40 data, this is a cache hit
  1043. _psb->_fldBase._fld._dwViewPriority = VIEW_PRIORITY_CACHEHIT;
  1044. }
  1045. }
  1046. // We let ambients take precedence over what we have persisted
  1047. VARIANT_BOOL fAmbient;
  1048. if (SUPERCLASS::_GetAmbientProperty(DISPID_AMBIENT_OFFLINEIFNOTCONNECTED, VT_BOOL, &fAmbient))
  1049. {
  1050. put_Offline(fAmbient);
  1051. }
  1052. else
  1053. {
  1054. put_Offline((sPersist.ie40.fFlags & SVO_FLAGS_OFFLINE) ? -1 : FALSE);
  1055. }
  1056. if (SUPERCLASS::_GetAmbientProperty(DISPID_AMBIENT_SILENT, VT_BOOL, &fAmbient))
  1057. {
  1058. put_Silent(fAmbient);
  1059. }
  1060. else
  1061. {
  1062. put_Silent((sPersist.ie40.fFlags & SVO_FLAGS_SILENT) ? -1 : FALSE);
  1063. }
  1064. put_RegisterAsDropTarget(BOOL_TO_VARIANTBOOL(sPersist.ie40.fFlags & SVO_FLAGS_REGISTERASDROPTGT));
  1065. _fShouldRegisterAsBrowser = (sPersist.ie40.fFlags & SVO_FLAGS_REGISTERASBROWSER) ? TRUE : FALSE;
  1066. // remember this for later
  1067. dwExtra = sPersist.ie40.dwExtra;
  1068. }
  1069. else
  1070. {
  1071. // if CLSID_WebBrowser_V1 reads an old stream format,
  1072. // it means that we must write out an old stream format later
  1073. // remember this...
  1074. if (_pObjectInfo->lVersion == VERSION_1)
  1075. {
  1076. _fEmulateOldStream = TRUE;
  1077. }
  1078. } // read ie40 data
  1079. }
  1080. // if we read all the data then make sure we're at
  1081. // the end of the stream
  1082. if (SUCCEEDED(hres) && _fInit)
  1083. {
  1084. //liMove.LowPart = liEnd.LowPart;
  1085. //hres = pstm->Seek(liMove, STREAM_SEEK_SET, NULL);
  1086. // now we can read in extra streamed data if we have it
  1087. if (dwExtra & SVO_EXTRA_TOOLBARS)
  1088. {
  1089. DWORD dwTotal;
  1090. hres = pstm->Read(&dwTotal, SIZEOF(dwTotal), NULL);
  1091. if (SUCCEEDED(hres))
  1092. {
  1093. ASSERT(dwTotal >= SIZEOF(dwTotal));
  1094. dwTotal -= SIZEOF(dwTotal);
  1095. if (_hmemSB)
  1096. {
  1097. GlobalFree(_hmemSB);
  1098. }
  1099. _hmemSB = GlobalAlloc(GPTR, dwTotal);
  1100. if (_hmemSB)
  1101. {
  1102. hres = pstm->Read((BYTE*)_hmemSB, dwTotal, NULL);
  1103. }
  1104. else
  1105. {
  1106. hres = E_OUTOFMEMORY;
  1107. }
  1108. }
  1109. }
  1110. }
  1111. }
  1112. }
  1113. }
  1114. _OnLoaded(FAILED(hresNavigate));
  1115. if (SUCCEEDED(hres))
  1116. hres = S_OK; // convert S_FALSE to S_OK
  1117. return hres;
  1118. }
  1119. HRESULT CWebBrowserOC_SavePersistData(IStream *pstm, SIZE* psizeObj,
  1120. FOLDERSETTINGS* pfs, IShellLinkA* plinkA, SHELLVIEWID* pvid,
  1121. BOOL fOffline, BOOL fSilent, BOOL fRegisterAsBrowser, BOOL fRegisterAsDropTarget,
  1122. BOOL fEmulateOldStream, DWORD *pdwExtra)
  1123. {
  1124. ULONG cbWritten;
  1125. PersistSVOCX sPersist;
  1126. HRESULT hres;
  1127. // This means that this instance of CWebBrowserOC was created using
  1128. // the ie30 CLSID and we were persisted from an old format stream.
  1129. // Under this scenario, we have to write out a stream format that
  1130. // can be read by the old ie30 object.
  1131. if (fEmulateOldStream && pdwExtra)
  1132. {
  1133. // The only data we stream out that can't be read back in by
  1134. // the old ie30 webbrowser is the dwExtra data.
  1135. *pdwExtra = 0;
  1136. }
  1137. ZeroMemory(&sPersist, SIZEOF(sPersist));
  1138. sPersist.ie30.cbSize = fEmulateOldStream ? SIZEOF(sPersist.ie30) : SIZEOF(sPersist);
  1139. sPersist.ie30.sizeObject = *psizeObj;
  1140. sPersist.ie30.fs = *pfs;
  1141. sPersist.ie30.dwOffPersistLink = SIZEOF(sPersist);
  1142. if (pvid)
  1143. {
  1144. sPersist.ie40.bRestoreView = TRUE;
  1145. sPersist.ie40.vid = *pvid;
  1146. }
  1147. sPersist.ie40.dwExtra = pdwExtra ? *pdwExtra : 0;
  1148. if (fOffline)
  1149. sPersist.ie40.fFlags |= SVO_FLAGS_OFFLINE;
  1150. if (fSilent)
  1151. sPersist.ie40.fFlags |= SVO_FLAGS_SILENT;
  1152. if (fRegisterAsBrowser)
  1153. sPersist.ie40.fFlags |= SVO_FLAGS_REGISTERASBROWSER;
  1154. if (fRegisterAsDropTarget)
  1155. sPersist.ie40.fFlags |= SVO_FLAGS_REGISTERASDROPTGT;
  1156. sPersist.ie40.dwVersion = SVO_VERSION;
  1157. hres = pstm->Write(&sPersist, SIZEOF(sPersist), &cbWritten);
  1158. IPSMSG3(TEXT("Save 1st Write(&_size) returned"), hres, cbWritten, sizeof(*psizeObj));
  1159. if (SUCCEEDED(hres))
  1160. {
  1161. // Save plinkA
  1162. ASSERT(plinkA);
  1163. IPersistStream* ppstm;
  1164. hres = plinkA->QueryInterface(IID_PPV_ARG(IPersistStream, &ppstm));
  1165. if (SUCCEEDED(hres))
  1166. {
  1167. hres = ppstm->Save(pstm, TRUE);
  1168. IPSMSG2(TEXT("Save plink->Save() returned"), hres);
  1169. ppstm->Release();
  1170. }
  1171. }
  1172. return hres;
  1173. }
  1174. BOOL CWebBrowserOC::_GetViewInfo(SHELLVIEWID* pvid)
  1175. {
  1176. BOOL bGotView = FALSE;
  1177. if (_psb)
  1178. {
  1179. if (_psb->GetShellView())
  1180. {
  1181. _psb->GetShellView()->GetCurrentInfo(&_fs);
  1182. }
  1183. else
  1184. {
  1185. _fs = _psb->_fldBase._fld._fs;
  1186. }
  1187. bGotView = FileCabinet_GetDefaultViewID2(&_psb->_fldBase, pvid);
  1188. }
  1189. return bGotView;
  1190. }
  1191. HRESULT CWebBrowserOC::Save(IStream *pstm, BOOL fClearDirty)
  1192. {
  1193. HRESULT hres;
  1194. LPITEMIDLIST pidl;
  1195. SHELLVIEWID vid;
  1196. BOOL bGotView;
  1197. VARIANT_BOOL fOffline, fSilent, fRegDT;
  1198. IPSMSG(TEXT("Save"));
  1199. IS_INITIALIZED;
  1200. pidl = NULL;
  1201. if (_psb)
  1202. pidl = _psb->_bbd._pidlCur;
  1203. // we need an IShellLink to save with
  1204. if (_plinkA == NULL)
  1205. {
  1206. hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IShellLinkA, &_plinkA));
  1207. if (FAILED(hres))
  1208. return hres;
  1209. }
  1210. _plinkA->SetIDList(pidl);
  1211. bGotView = _GetViewInfo(&vid);
  1212. DWORD dwExtra = 0;
  1213. #if 0
  1214. if (_psb && _psb->_SaveToolbars(NULL)==S_OK) {
  1215. dwExtra |= SVO_EXTRA_TOOLBARS;
  1216. }
  1217. #endif
  1218. get_Offline(&fOffline);
  1219. get_Silent(&fSilent);
  1220. get_RegisterAsDropTarget(&fRegDT);
  1221. hres = CWebBrowserOC_SavePersistData(pstm, _fEmulateOldStream ? &_size : &_sizeHIM, &_fs, _plinkA,
  1222. (bGotView ? &vid : NULL),
  1223. fOffline, fSilent, _fShouldRegisterAsBrowser, fRegDT,
  1224. _fEmulateOldStream, &dwExtra);
  1225. ASSERT(!(dwExtra & SVO_EXTRA_TOOLBARS));
  1226. #if 0
  1227. if (SUCCEEDED(hres) && (dwExtra & SVO_EXTRA_TOOLBARS))
  1228. {
  1229. // Remember the current location.
  1230. ULARGE_INTEGER liStart;
  1231. pstm->Seek(c_li0, STREAM_SEEK_CUR, &liStart);
  1232. // Write the dummy size.
  1233. DWORD dwTotal = 0;
  1234. hres = pstm->Write(&dwTotal, SIZEOF(dwTotal), NULL);
  1235. if (SUCCEEDED(hres)) {
  1236. if (_psb)
  1237. hres = _psb->_SaveToolbars(pstm);
  1238. // Remember the end
  1239. ULARGE_INTEGER liEnd;
  1240. pstm->Seek(c_li0, STREAM_SEEK_CUR, &liEnd);
  1241. // Seek back to the original location
  1242. LARGE_INTEGER liT;
  1243. liT.HighPart = 0;
  1244. liT.LowPart = liStart.LowPart;
  1245. pstm->Seek(liT, STREAM_SEEK_SET, NULL);
  1246. // Get the real dwTotal and write it
  1247. dwTotal = liEnd.LowPart - liStart.LowPart;
  1248. hres = pstm->Write(&dwTotal, SIZEOF(dwTotal), NULL);
  1249. // Seek forward to the end
  1250. liT.LowPart = liEnd.LowPart;
  1251. pstm->Seek(liT, STREAM_SEEK_SET, NULL);
  1252. }
  1253. }
  1254. #endif
  1255. if (fClearDirty)
  1256. {
  1257. _fDirty = FALSE;
  1258. }
  1259. return hres;
  1260. }
  1261. void CWebBrowserOC::_OnLoaded(BOOL fUpdateBrowserReadyState)
  1262. {
  1263. IEFrameAuto * piefa;
  1264. if (SUCCEEDED(_pauto->QueryInterface(IID_PPV_ARG(IEFrameAuto, &piefa))))
  1265. {
  1266. piefa->put_DefaultReadyState(READYSTATE_COMPLETE, fUpdateBrowserReadyState);
  1267. piefa->Release();
  1268. }
  1269. }
  1270. HRESULT CWebBrowserOC::InitNew(void)
  1271. {
  1272. IPSMSG(TEXT("InitNew"));
  1273. _InitDefault();
  1274. // On the InitNew case, we do want to update the browser's ready state
  1275. _OnLoaded(TRUE);
  1276. return NOERROR;
  1277. }
  1278. // IPersistPropertyBag
  1279. static const struct {
  1280. LPOLESTR pName;
  1281. UINT flag;
  1282. } g_boolprops[] = {
  1283. {L"AutoArrange", FWF_AUTOARRANGE},
  1284. {L"NoClientEdge", FWF_NOCLIENTEDGE},
  1285. {L"AlignLeft", FWF_ALIGNLEFT},
  1286. {L"NoWebView", FWF_NOWEBVIEW},
  1287. {L"HideFileNames", FWF_HIDEFILENAMES},
  1288. {L"SingleClick", FWF_SINGLECLICKACTIVATE},
  1289. {L"SingleSelection", FWF_SINGLESEL},
  1290. {L"NoFolders", FWF_NOSUBFOLDERS},
  1291. {L"Transparent", FWF_TRANSPARENT},
  1292. };
  1293. HRESULT CWebBrowserOC::Load(IPropertyBag *pBag, IErrorLog *pErrorLog)
  1294. {
  1295. BOOL fOffline = FALSE;
  1296. BOOL fSilent = FALSE;
  1297. BOOL fRegisterAsBrowser = FALSE;
  1298. BOOL fRegisterAsDropTgt = FALSE;
  1299. BOOL fUpdateBrowserReadyState = TRUE;
  1300. VARIANT_BOOL fAmbient;
  1301. // It is illegal to call ::Load or ::InitNew more than once
  1302. if (_fInit)
  1303. {
  1304. TraceMsg(TF_SHDCONTROL, "shv IPersistPropertyBag::Load called when ALREADY INITIALIZED!");
  1305. ASSERT(FALSE);
  1306. return E_FAIL;
  1307. }
  1308. _InitDefault();
  1309. // grab all our DWORD-sized (VT_UI4) properties
  1310. struct {
  1311. LPOLESTR pName;
  1312. DWORD* pdw;
  1313. } rgLoadProps[] = {
  1314. {L"Height", (DWORD *)&_size.cy},
  1315. {L"Width", (DWORD *)&_size.cx},
  1316. {L"ViewMode", (DWORD *)&_fs.ViewMode},
  1317. {L"Offline", (DWORD *)&fOffline},
  1318. {L"Silent", (DWORD *)&fSilent},
  1319. {L"RegisterAsBrowser", (DWORD *)&fRegisterAsBrowser},
  1320. {L"RegisterAsDropTarget", (DWORD *)&fRegisterAsDropTgt}
  1321. };
  1322. for (int i = 0; i < ARRAYSIZE(rgLoadProps); i++)
  1323. {
  1324. SHPropertyBag_ReadDWORD(pBag, rgLoadProps[i].pName, rgLoadProps[i].pdw);
  1325. }
  1326. // We let ambients take precedence over what we have persisted
  1327. if (SUPERCLASS::_GetAmbientProperty(DISPID_AMBIENT_OFFLINEIFNOTCONNECTED, VT_BOOL, &fAmbient))
  1328. {
  1329. put_Offline(fAmbient);
  1330. }
  1331. else
  1332. {
  1333. put_Offline(BOOL_TO_VARIANTBOOL(fOffline));
  1334. }
  1335. if (SUPERCLASS::_GetAmbientProperty(DISPID_AMBIENT_SILENT, VT_BOOL, &fAmbient))
  1336. {
  1337. put_Silent(fAmbient);
  1338. }
  1339. else
  1340. {
  1341. put_Silent(BOOL_TO_VARIANTBOOL(fSilent));
  1342. }
  1343. // If You use fOffline or fSilent after this, you will have to re-init them according
  1344. // to the returned values of fAmbient in the if statements above
  1345. put_RegisterAsDropTarget(BOOL_TO_VARIANTBOOL(fRegisterAsDropTgt));
  1346. _fShouldRegisterAsBrowser = VARIANTBOOL_TO_BOOL(fRegisterAsBrowser);
  1347. // IE3 saved PIXEL size, IE4 saves HIMETRIC size
  1348. DWORD lVal;
  1349. HRESULT hr = SHPropertyBag_ReadDWORD(pBag, L"ExtentX", &lVal);
  1350. if (SUCCEEDED(hr))
  1351. {
  1352. _sizeHIM.cx = lVal;
  1353. hr = SHPropertyBag_ReadDWORD(pBag, L"ExtentY", &lVal);
  1354. if (SUCCEEDED(hr))
  1355. {
  1356. _sizeHIM.cy = lVal;
  1357. }
  1358. }
  1359. if (FAILED(hr))
  1360. {
  1361. // convert IE3 info to HIMETRIC
  1362. _sizeHIM = _size;
  1363. PixelsToMetric(&_sizeHIM);
  1364. }
  1365. hr = S_OK;
  1366. for (i = 0; i < ARRAYSIZE(g_boolprops); i++)
  1367. {
  1368. if (SHPropertyBag_ReadBOOLDefRet(pBag, g_boolprops[i].pName, FALSE))
  1369. _fs.fFlags |= g_boolprops[i].flag;
  1370. else
  1371. _fs.fFlags &= ~g_boolprops[i].flag;
  1372. }
  1373. // grab special properties
  1374. if (_psb) // if no _psb then container ignored OLEMISC_SETCLIENTSITEFIRST
  1375. {
  1376. if (SUCCEEDED(SHPropertyBag_ReadGUID(pBag, L"ViewID", &_psb->_fldBase._fld._vidRestore)))
  1377. {
  1378. // we sucessfully read the ViewID, so this is a cache hit
  1379. _psb->_fldBase._fld._dwViewPriority = VIEW_PRIORITY_CACHEHIT;
  1380. }
  1381. _psb->_fldBase._fld._fs = _fs;
  1382. BSTR bstrVal;
  1383. if (SUCCEEDED(SHPropertyBag_ReadBSTR(pBag, L"Location", &bstrVal)))
  1384. {
  1385. ASSERT(FALSE == _psb->_fAsyncNavigate);
  1386. hr = WrapSpecialUrl(&bstrVal);
  1387. if (SUCCEEDED(hr))
  1388. {
  1389. _psb->_fAsyncNavigate = TRUE;
  1390. if (FAILED(Navigate(bstrVal, NULL, NULL, NULL, NULL)))
  1391. {
  1392. TraceMsg(TF_SHDCONTROL, "Load PropertyBag Navigate FAILED!");
  1393. }
  1394. else
  1395. {
  1396. // Navigate is successful (at least initially), let it update ReadyState
  1397. //
  1398. fUpdateBrowserReadyState = FALSE;
  1399. }
  1400. _psb->_fAsyncNavigate = FALSE;
  1401. }
  1402. SysFreeString(bstrVal);
  1403. }
  1404. }
  1405. _OnLoaded(fUpdateBrowserReadyState);
  1406. return hr;
  1407. }
  1408. HRESULT CWebBrowserOC::Save(IPropertyBag *pBag, BOOL fClearDirty, BOOL fSaveAllProperties)
  1409. {
  1410. IS_INITIALIZED;
  1411. HRESULT hres;
  1412. VARIANT var;
  1413. int i;
  1414. SHELLVIEWID vid;
  1415. BOOL bGotView = FALSE;
  1416. VARIANT_BOOL f;
  1417. BOOL fOffline;
  1418. BOOL fSilent;
  1419. BOOL fRegisterAsDropTgt;
  1420. BOOL fRegisterAsBrowser;
  1421. get_Offline(&f);
  1422. fOffline = f ? TRUE : FALSE;
  1423. get_Silent(&f);
  1424. fSilent = f ? TRUE : FALSE;
  1425. get_RegisterAsDropTarget(&f);
  1426. fRegisterAsDropTgt = f ? TRUE : FALSE;
  1427. fRegisterAsBrowser = _fShouldRegisterAsBrowser ? TRUE : FALSE;
  1428. // our state may have changed
  1429. bGotView = _GetViewInfo(&vid);
  1430. // save all our DWORD-sized properties
  1431. struct {
  1432. LPOLESTR pName;
  1433. DWORD* pdw;
  1434. } rgLoadProps[] = {
  1435. {L"ExtentX", (DWORD *)&_sizeHIM.cx},
  1436. {L"ExtentY", (DWORD *)&_sizeHIM.cy},
  1437. {L"ViewMode", (DWORD *)&_fs.ViewMode},
  1438. {L"Offline", (DWORD *)&fOffline},
  1439. {L"Silent", (DWORD *)&fSilent},
  1440. {L"RegisterAsBrowser", (DWORD *)&fRegisterAsBrowser},
  1441. {L"RegisterAsDropTarget", (DWORD *)&fRegisterAsDropTgt},
  1442. // IE3 OC stuff here
  1443. {L"Height", (DWORD *)&_size.cy},
  1444. {L"Width", (DWORD *)&_size.cx}
  1445. };
  1446. VariantInit(&var);
  1447. var.vt = VT_I4; // VB doesn't understand VT_UI4! (pBag->Write succeeds,
  1448. // but it doesn't write anything! The load then fails!)
  1449. int nCount = ARRAYSIZE(rgLoadProps);
  1450. if (_pObjectInfo->lVersion != VERSION_1)
  1451. nCount -= 2;
  1452. for (i = 0; i < nCount; i++)
  1453. {
  1454. var.lVal = *rgLoadProps[i].pdw;
  1455. hres = pBag->Write(rgLoadProps[i].pName, &var);
  1456. if (FAILED(hres))
  1457. {
  1458. TraceMsg(TF_SHDCONTROL, "Save PropertyBag could not save %ws for DWORD", rgLoadProps[i].pName);
  1459. return hres;
  1460. }
  1461. }
  1462. // save all our _fs.fFlags (VT_BOOL) flags
  1463. var.vt = VT_BOOL;
  1464. for (i = 0; i < ARRAYSIZE(g_boolprops); i++)
  1465. {
  1466. var.boolVal = BOOL_TO_VARIANTBOOL(_fs.fFlags & g_boolprops[i].flag);
  1467. hres = pBag->Write(g_boolprops[i].pName, &var);
  1468. if (FAILED(hres))
  1469. {
  1470. TraceMsg(TF_SHDCONTROL, "Load PropertyBag did not save %ws for BOOL", g_boolprops[i].pName);
  1471. }
  1472. }
  1473. // save special properties
  1474. if (bGotView)
  1475. {
  1476. SHPropertyBag_WriteGUID(pBag, L"ViewID", &(GUID)vid);
  1477. }
  1478. var.vt = VT_BSTR;
  1479. if (SUCCEEDED(get_LocationURL(&var.bstrVal)))
  1480. {
  1481. hres = pBag->Write(L"Location", &var);
  1482. VariantClear(&var);
  1483. if (FAILED(hres))
  1484. {
  1485. TraceMsg(TF_SHDCONTROL, "Save PropertyBag could not save Location");
  1486. return hres;
  1487. }
  1488. }
  1489. else
  1490. {
  1491. var.vt = VT_EMPTY;
  1492. TraceMsg(TF_SHDCONTROL, "Save PropertyBag get_Location FAILED!");
  1493. }
  1494. return NOERROR;
  1495. }
  1496. // IPersistString
  1497. STDMETHODIMP CWebBrowserOC::Initialize(LPCWSTR pwszInit)
  1498. {
  1499. HRESULT hr = E_OUTOFMEMORY;
  1500. BSTR bstr = SysAllocString(pwszInit);
  1501. if (bstr)
  1502. {
  1503. hr = Navigate(bstr, NULL, NULL, NULL, NULL);
  1504. SysFreeString(bstr);
  1505. }
  1506. return hr;
  1507. }
  1508. #define THISCLASS CWebBrowserOC
  1509. HRESULT CWebBrowserOC::v_InternalQueryInterface(REFIID riid, void ** ppvObj)
  1510. {
  1511. static const QITAB qit[] = {
  1512. QITABENT(THISCLASS, IWebBrowser2),
  1513. QITABENTMULTI(THISCLASS, IDispatch, IWebBrowser2), // VBA QI's IDispatch and assumes it gets the "default" automation interface, which is IWebBrowser2
  1514. QITABENTMULTI(THISCLASS, IWebBrowser, IWebBrowser2),
  1515. QITABENTMULTI(THISCLASS, IWebBrowserApp, IWebBrowser2),
  1516. QITABENT(THISCLASS, IPersistString),
  1517. QITABENT(THISCLASS, IOleCommandTarget),
  1518. QITABENT(THISCLASS, IObjectSafety),
  1519. QITABENT(THISCLASS, ITargetEmbedding),
  1520. QITABENT(THISCLASS, IExpDispSupport),
  1521. QITABENT(THISCLASS, IExpDispSupportOC),
  1522. QITABENT(THISCLASS, IPersistHistory),
  1523. QITABENT(THISCLASS, IPersistStorage),
  1524. { 0 },
  1525. };
  1526. HRESULT hres = QISearch(this, qit, riid, ppvObj);
  1527. if (FAILED(hres))
  1528. {
  1529. hres = SUPERCLASS::v_InternalQueryInterface(riid, ppvObj);
  1530. // we want to expose our aggregated CIEFrameAuto's interfaces
  1531. // in addition to ours.
  1532. if (FAILED(hres))
  1533. {
  1534. hres = _pauto->QueryInterface(riid, ppvObj);
  1535. }
  1536. }
  1537. return hres;
  1538. }
  1539. // *** IOleInPlaceActiveObject ***
  1540. HRESULT CWebBrowserOC::OnFrameWindowActivate(BOOL fActivate)
  1541. {
  1542. if (_psb)
  1543. _psb->OnFrameWindowActivateBS(fActivate);
  1544. return S_OK;
  1545. }
  1546. HRESULT CWebBrowserOC::TranslateAccelerator(LPMSG lpMsg)
  1547. {
  1548. if (_psb)
  1549. {
  1550. // FEATURE REVIEW: what wID should we really pass? Is 0 ok?
  1551. if (S_OK == _psb->_TranslateAccelerator(lpMsg, 0, DIRECTION_FORWARD_TO_CHILD))
  1552. return S_OK;
  1553. }
  1554. else
  1555. {
  1556. IOIPAMSG(TEXT("TranslateAccelerator cannot forward to _psb"));
  1557. }
  1558. // SUPERCLASS has no accelerators
  1559. return S_FALSE;
  1560. }
  1561. HRESULT CWebBrowserOC::EnableModeless(BOOL fEnable)
  1562. {
  1563. SUPERCLASS::EnableModeless(fEnable);
  1564. if (_psb)
  1565. {
  1566. return _psb->_EnableModeless(fEnable, DIRECTION_FORWARD_TO_CHILD);
  1567. }
  1568. else
  1569. {
  1570. IOIPAMSG(TEXT("EnableModeless cannot forward to _psb"));
  1571. return S_OK;
  1572. }
  1573. }
  1574. HRESULT CWebBrowserOC::_OnActivateChange(IOleClientSite* pActiveSite, UINT uState)
  1575. {
  1576. HRESULT hres = SUPERCLASS::_OnActivateChange(pActiveSite, uState);
  1577. if (SUCCEEDED(hres))
  1578. {
  1579. UINT uViewState;
  1580. switch (uState)
  1581. {
  1582. case OC_DEACTIVE: uViewState = SVUIA_DEACTIVATE; break;
  1583. case OC_INPLACEACTIVE: uViewState = SVUIA_INPLACEACTIVATE; break;
  1584. case OC_UIACTIVE: uViewState = SVUIA_ACTIVATE_FOCUS; break;
  1585. default: ASSERT(FALSE); return E_INVALIDARG;
  1586. }
  1587. if (_psb)
  1588. _psb->_UIActivateView(uViewState);
  1589. }
  1590. else
  1591. {
  1592. TraceMsg(TF_SHDCONTROL, "shv _OnActivateChange failed, _psb=0x%x", _psb);
  1593. }
  1594. return hres;
  1595. }
  1596. void CWebBrowserOC::_OnInPlaceActivate(void)
  1597. {
  1598. HWND hwnd = NULL;
  1599. SUPERCLASS::_OnInPlaceActivate();
  1600. _RegisterWindow();
  1601. if (_pipsite)
  1602. {
  1603. // we have to hold on to the target frame until we deactivate,
  1604. // because the psbFrame will delete this thing when it shuts down
  1605. // *before* we are actually deactivated, leaking the unadvise
  1606. // in ieframeauto.
  1607. ASSERT(NULL==_pTargetFramePriv);
  1608. if (SUCCEEDED(IUnknown_QueryService(_pipsite, IID_ITargetFrame2, IID_PPV_ARG(ITargetFramePriv, &_pTargetFramePriv))))
  1609. {
  1610. _pTargetFramePriv->OnChildFrameActivate(SAFECAST(this, IConnectionPointContainer* ));
  1611. }
  1612. ASSERT(NULL==_pctContainer);
  1613. if (FAILED(_pipsite->QueryInterface(IID_PPV_ARG(IOleCommandTarget, &_pctContainer))))
  1614. {
  1615. // NT 305187 discover.exe crash on exit when _pcli is NULL
  1616. if (_pcli)
  1617. {
  1618. // APPCOMPAT: It should be on IOleInPlaceSite,
  1619. // but MSHTML currently has it on IOleContainer.
  1620. IOleContainer *pCont;
  1621. if (SUCCEEDED(_pcli->GetContainer(&pCont)))
  1622. {
  1623. pCont->QueryInterface(IID_PPV_ARG(IOleCommandTarget, &_pctContainer));
  1624. pCont->Release();
  1625. }
  1626. }
  1627. }
  1628. if (_pipframe && SUCCEEDED(_pipframe->GetWindow(&hwnd)))
  1629. {
  1630. // Check to see if our inplace frame is VB5. If so, we have to hack around
  1631. // _pipframe->EnableModeless calls
  1632. //
  1633. const TCHAR VBM_THUNDER[] = TEXT("Thunder");
  1634. TCHAR strBuf[VB_CLASSNAME_LENGTH];
  1635. // Check to see if the inplace frame we just called is VB5's forms engine.
  1636. //
  1637. memset(strBuf, 0, ARRAYSIZE(strBuf)); // Clear the buffer
  1638. GetClassName(hwnd, strBuf, (VB_CLASSNAME_LENGTH - 1)); // Get the class name of the window.
  1639. if (StrCmpN(strBuf, VBM_THUNDER, (sizeof(VBM_THUNDER)/sizeof(TCHAR))-1) == 0) // Is the first part "Thunder"?
  1640. {
  1641. _fHostedInVB5 = TRUE;
  1642. }
  1643. }
  1644. {
  1645. //
  1646. // App compat: Check for imagineer technical
  1647. //
  1648. const WCHAR STR_IMAGINEER[] = L"imagine.exe";
  1649. WCHAR szBuff[MAX_PATH];
  1650. if (GetModuleFileName(NULL, szBuff, ARRAYSIZE(szBuff)))
  1651. {
  1652. LPWSTR pszFile = PathFindFileName(szBuff);
  1653. if (pszFile)
  1654. {
  1655. _fHostedInImagineer = (0 == StrNCmpI(pszFile, STR_IMAGINEER,
  1656. ARRAYSIZE(STR_IMAGINEER) - 1));
  1657. }
  1658. }
  1659. }
  1660. }
  1661. else
  1662. {
  1663. IOIPAMSG(TEXT("_OnInPlaceActivate doesn't have pipsite!"));
  1664. }
  1665. }
  1666. void CWebBrowserOC::_OnInPlaceDeactivate(void)
  1667. {
  1668. _UnregisterWindow();
  1669. if (_pTargetFramePriv)
  1670. {
  1671. _pTargetFramePriv->OnChildFrameDeactivate(SAFECAST(this, IConnectionPointContainer*));
  1672. ATOMICRELEASE(_pTargetFramePriv);
  1673. }
  1674. ATOMICRELEASE(_pctContainer);
  1675. SUPERCLASS::_OnInPlaceDeactivate();
  1676. }
  1677. /*
  1678. ** Ambient properties we care about
  1679. */
  1680. // We forward IOleControl calls to the docobj.
  1681. // This helper function returns the docobj's IOleControl interface.
  1682. //
  1683. // NOTE: we may want to fail this when the WebBrowserOC was created
  1684. // using IE3's classid just to be safe...
  1685. //
  1686. IOleControl* GetForwardingIOC(IWebBrowser* pwb)
  1687. {
  1688. IOleControl* poc = NULL;
  1689. IDispatch* pdisp;
  1690. if (SUCCEEDED(pwb->get_Document(&pdisp)))
  1691. {
  1692. pdisp->QueryInterface(IID_PPV_ARG(IOleControl, &poc));
  1693. pdisp->Release();
  1694. }
  1695. return poc;
  1696. }
  1697. STDMETHODIMP CWebBrowserOC::GetControlInfo(LPCONTROLINFO pCI)
  1698. {
  1699. HRESULT hres = E_NOTIMPL;
  1700. // REVIEW: What if we return some docobjects CONTROLINFO here and
  1701. // we navigate somewhere else. Do we have to know when this
  1702. // happens and tell our container that the CONTROLINFO has
  1703. // changed??
  1704. IOleControl* poc = GetForwardingIOC(_pautoWB2);
  1705. if (poc)
  1706. {
  1707. hres = poc->GetControlInfo(pCI);
  1708. poc->Release();
  1709. }
  1710. return hres;
  1711. }
  1712. STDMETHODIMP CWebBrowserOC::OnMnemonic(LPMSG pMsg)
  1713. {
  1714. HRESULT hres = E_NOTIMPL;
  1715. IOleControl* poc = GetForwardingIOC(_pautoWB2);
  1716. if (poc)
  1717. {
  1718. hres = poc->OnMnemonic(pMsg);
  1719. poc->Release();
  1720. }
  1721. return hres;
  1722. }
  1723. HRESULT __stdcall CWebBrowserOC::OnAmbientPropertyChange(DISPID dispid)
  1724. {
  1725. IS_INITIALIZED;
  1726. // First let our base class know about the change
  1727. //
  1728. SUPERCLASS::OnAmbientPropertyChange(dispid);
  1729. // Forward ambient property changes down to the docobject
  1730. // if it is something other than offline or silent
  1731. // for offline and silent, we call the methods to set
  1732. // the properties so that we remember it and these
  1733. // methods forward downwards on their own and so we we
  1734. // end up forwarding twice.
  1735. if((dispid == DISPID_AMBIENT_OFFLINEIFNOTCONNECTED) || (dispid == DISPID_AMBIENT_SILENT))
  1736. {
  1737. VARIANT_BOOL fAmbient;
  1738. if (SUPERCLASS::_GetAmbientProperty(dispid, VT_BOOL, &fAmbient))
  1739. {
  1740. if (dispid == DISPID_AMBIENT_OFFLINEIFNOTCONNECTED)
  1741. {
  1742. put_Offline(fAmbient);
  1743. }
  1744. else if(dispid == DISPID_AMBIENT_SILENT)
  1745. {
  1746. put_Silent(fAmbient);
  1747. }
  1748. }
  1749. // return ; // BharatS 01/20/97
  1750. // APPCOMPAT --- This could be avoided if the forwarding
  1751. // from simply calling put_offline worked fine but it does not
  1752. // and so the second forwarding can be removed when that is fixed
  1753. }
  1754. IOleControl* poc = GetForwardingIOC(_pautoWB2);
  1755. if (poc)
  1756. {
  1757. poc->OnAmbientPropertyChange(dispid);
  1758. poc->Release();
  1759. }
  1760. return S_OK;
  1761. }
  1762. STDMETHODIMP CWebBrowserOC::FreezeEvents(BOOL bFreeze)
  1763. {
  1764. // First let our base class know about the change
  1765. //
  1766. SUPERCLASS::FreezeEvents(bFreeze);
  1767. // Forward this down to the docobject
  1768. //
  1769. IOleControl* poc = GetForwardingIOC(_pautoWB2);
  1770. // delegate only if the freezeevents count is balanced when
  1771. // you receive a FALSE. There may be FALSE calls coming in,
  1772. // before we get a chance to delegate the pending freezeevents calls
  1773. // TRUE is always delegated.
  1774. if (poc && (bFreeze || (_cPendingFreezeEvents == 0)))
  1775. {
  1776. poc->FreezeEvents(bFreeze);
  1777. }
  1778. else
  1779. {
  1780. // keeping a total number of FreezeEvents(TRUE) calls
  1781. // that we have to make up for.
  1782. if ( bFreeze )
  1783. {
  1784. _cPendingFreezeEvents++;
  1785. }
  1786. else
  1787. {
  1788. // Don't let this go negative, otherwise we'll send 4 billion FreezeEvents(TRUE)
  1789. // to the DocObject in CWebBrowserOC::_OnSetShellView. (QFE [alanau])(ferhane)
  1790. if (EVAL(_cPendingFreezeEvents > 0))
  1791. {
  1792. _cPendingFreezeEvents --;
  1793. }
  1794. }
  1795. }
  1796. if (poc)
  1797. poc->Release();
  1798. return S_OK;
  1799. }
  1800. // CWebBrowserSB just started viewing psvNew - do our OC stuff now
  1801. //
  1802. void CWebBrowserOC::_OnSetShellView(IShellView* psvNew)
  1803. {
  1804. _fDirty = TRUE;
  1805. // NOTE: Document, Type, LocationName, LocationURL, Busy just changed...
  1806. // PropertyChanged(DISPID_LOCATION);
  1807. // NOTE: that is the job of the CBaseBrowser to tell us really.
  1808. // ideally we would not put this here at all (or in _OnReleaseShellV...
  1809. _SendAdvise(OBJECTCODE_DATACHANGED); // implies OBJECTCODE_VIEWCHANGED
  1810. // we might have received FreezeEvents(TRUE) calls from the container
  1811. // and if the document was not ready, we might not have had a chance
  1812. // to pass them down the stream. This is the time to make up for it.
  1813. if (_cPendingFreezeEvents > 0)
  1814. {
  1815. IOleControl* poc = GetForwardingIOC(_pautoWB2);
  1816. if (poc)
  1817. {
  1818. for ( ; _cPendingFreezeEvents > 0; _cPendingFreezeEvents-- )
  1819. {
  1820. // Forward this down to the docobject
  1821. poc->FreezeEvents(TRUE);
  1822. }
  1823. poc->Release();
  1824. }
  1825. }
  1826. }
  1827. // CWebBrowserSB is releasing the currently viewed IShellView
  1828. void CWebBrowserOC::_OnReleaseShellView()
  1829. {
  1830. }
  1831. // *** IOleCommandTarget
  1832. //
  1833. // our version simply forwards to the object below our CWebBrowserSB
  1834. //
  1835. HRESULT CWebBrowserOC::QueryStatus(const GUID *pguidCmdGroup, ULONG cCmds, OLECMD rgCmds[], OLECMDTEXT *pcmdtext)
  1836. {
  1837. if (_psb && _psb->_bbd._pctView)
  1838. return _psb->_bbd._pctView->QueryStatus(pguidCmdGroup, cCmds, rgCmds, pcmdtext);
  1839. return OLECMDERR_E_UNKNOWNGROUP;
  1840. }
  1841. HRESULT CWebBrowserOC::Exec(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANTARG *pvarargIn, VARIANTARG *pvarargOut)
  1842. {
  1843. HRESULT hr = OLECMDERR_E_UNKNOWNGROUP;
  1844. if (_psb)
  1845. {
  1846. if (pguidCmdGroup==NULL)
  1847. {
  1848. switch(nCmdID)
  1849. {
  1850. case OLECMDID_STOP:
  1851. {
  1852. LPITEMIDLIST pidlIntended = (_psb->_bbd._pidlPending) ? ILClone(_psb->_bbd._pidlPending) : NULL;
  1853. _psb->_CancelPendingNavigation();
  1854. // We've just canceled the pending navigation. We may not have a current page! The following
  1855. // accomplishes two goals:
  1856. //
  1857. // 1. Gives the user some information about the frame that couldn't navigate.
  1858. // 2. Allows the browser to reach READYSTATE_COMPLETE
  1859. //
  1860. if (!_psb->_bbd._pidlCur)
  1861. {
  1862. // We display the navcancl.htm page in most cases.
  1863. // However, we won't display it if the call has
  1864. // explicitly specified that we shouldn't.
  1865. //
  1866. if ( !pvarargIn
  1867. || V_VT(pvarargIn) != VT_BOOL
  1868. || V_BOOL(pvarargIn) == VARIANT_TRUE)
  1869. {
  1870. TCHAR szResURL[MAX_URL_STRING];
  1871. hr = MLBuildResURLWrap(TEXT("shdoclc.dll"),
  1872. HINST_THISDLL,
  1873. ML_CROSSCODEPAGE,
  1874. TEXT("navcancl.htm"),
  1875. szResURL,
  1876. ARRAYSIZE(szResURL),
  1877. TEXT("shdocvw.dll"));
  1878. if (SUCCEEDED(hr))
  1879. {
  1880. _psb->_ShowBlankPage(szResURL, pidlIntended);
  1881. }
  1882. }
  1883. }
  1884. if(pidlIntended)
  1885. ILFree(pidlIntended);
  1886. break; // Note that we need to fall through.
  1887. }
  1888. case OLECMDID_ENABLE_INTERACTION:
  1889. if (pvarargIn && pvarargIn->vt == VT_I4)
  1890. {
  1891. _psb->_fPausedByParent = BOOLIFY(pvarargIn->lVal);
  1892. }
  1893. break; // Note that we need to fall through.
  1894. }
  1895. hr = S_OK;
  1896. // WARNING: fall through to forward down
  1897. }
  1898. if (_psb->_bbd._pctView)
  1899. hr = _psb->_bbd._pctView->Exec(pguidCmdGroup, nCmdID, nCmdexecopt, pvarargIn, pvarargOut);
  1900. }
  1901. return hr;
  1902. }
  1903. //
  1904. // We hit this code if the normal IOleCommandTarget chain is broken (such as
  1905. // browser band in the browser bar). In this case, we get the command target
  1906. // to the top level browser and send OLECMDID_SETDOWNLOADSTATE to it.
  1907. //
  1908. // Returns:
  1909. // S_OK If we found the top level browser and it processed it.
  1910. // hresRet Otherwise
  1911. //
  1912. HRESULT CWebBrowserOC::_SetDownloadState(HRESULT hresRet, DWORD nCmdexecopt, VARIANTARG *pvarargIn)
  1913. {
  1914. ASSERT(hresRet == OLECMDERR_E_UNKNOWNGROUP || hresRet == OLECMDERR_E_NOTSUPPORTED);
  1915. IOleCommandTarget* pcmdtTop;
  1916. if (_psb && SUCCEEDED(_psb->_QueryServiceParent(SID_STopLevelBrowser, IID_PPV_ARG(IOleCommandTarget, &pcmdtTop))))
  1917. {
  1918. ASSERT(pcmdtTop != _psb);
  1919. VARIANTARG var;
  1920. if (pvarargIn && pvarargIn->lVal)
  1921. {
  1922. ASSERT(pvarargIn->vt == VT_I4 || pvarargIn->vt == VT_BOOL || pvarargIn->vt == VT_UNKNOWN);
  1923. //
  1924. // Notice that we pass the pointer to this OC so that the top
  1925. // level browser can keep track of it. This is a new behavior
  1926. // which is different from IE 3.0.
  1927. //
  1928. var.vt = VT_UNKNOWN;
  1929. var.punkVal = SAFECAST(this, IOleCommandTarget*);
  1930. }
  1931. else
  1932. {
  1933. var.vt = VT_BOOL;
  1934. var.lVal = FALSE;
  1935. }
  1936. HRESULT hresT = pcmdtTop->Exec(NULL, OLECMDID_SETDOWNLOADSTATE, nCmdexecopt, &var, NULL);
  1937. TraceMsg(DM_FORSEARCHBAND, "WBOC::_SetDownloadState pcmdTop->Exec returned %x", hresT);
  1938. if (SUCCEEDED(hresT))
  1939. {
  1940. hresRet = S_OK;
  1941. }
  1942. pcmdtTop->Release();
  1943. }
  1944. else
  1945. {
  1946. TraceMsg(DM_FORSEARCHBAND, "WBOC::_SetDownloadState can't find the top guy");
  1947. }
  1948. return hresRet;
  1949. }
  1950. #if 0 // not sure if this is correct, waiting for reply from OLEPSS alias
  1951. // VB is not happy if we fail a property get, so when an IDispatch
  1952. // is not safe we return an instance of this dummy IDispatch
  1953. class CDispatchDummy : public IDispatch
  1954. {
  1955. public:
  1956. CDispatchDummy() { m_cRef=1; DllAddRef(); };
  1957. ~CDispatchDummy() { DllRelease(); };
  1958. // IUnknown methods
  1959. STDMETHOD(QueryInterface(REFIID riid, void ** ppvObj);
  1960. STDMETHOD_(ULONG, AddRef)(THIS);
  1961. STDMETHOD_(ULONG, Release)(THIS);
  1962. // IDispatch methods
  1963. STDMETHOD(GetTypeInfoCount) (unsigned int *pctinfo)
  1964. { return E_FAIL; };
  1965. STDMETHOD(GetTypeInfo) (unsigned int itinfo, LCID lcid, ITypeInfo **pptinfo)
  1966. { return E_FAIL; };
  1967. STDMETHODIMP GetIDsOfNames(REFIID riid, OLECHAR **rgszNames, unsigned int cNames, LCID lcid, DISPID * rgdispid)
  1968. { return E_FAIL; };
  1969. STDMETHODIMP Invoke(DISPID dispidMember, REFIID iid, LCID lcid, WORD wFlags, DISPPARAMS * pdispparams,VARIANT * pvarResult,EXCEPINFO * pexcepinfo,UINT * puArgErr)
  1970. { return E_FAIL; };
  1971. protected:
  1972. ULONG m_cRef;
  1973. };
  1974. HRESULT CDispatchDummy::QueryInterface(REFIID riid, void ** ppvObj)
  1975. {
  1976. if (IsEqualIID(riid, IID_IDispatch) ||
  1977. IsEqualIID(riid, IID_IUnknown))
  1978. {
  1979. AddRef();
  1980. *ppvObj = SAFECAST(this, IDispatch*);
  1981. return S_OK;
  1982. }
  1983. return E_NOINTERFACE;
  1984. }
  1985. ULONG CDispatchDummy::AddRef(THIS)
  1986. {
  1987. return ++m_cRef;
  1988. }
  1989. ULONG CDispatchDummy::Release(THIS)
  1990. {
  1991. if (--m_cRef==0)
  1992. {
  1993. delete this;
  1994. return 0;
  1995. }
  1996. return m_cRef;
  1997. }
  1998. HRESULT CreateDummyDispatch(IDispatch** ppDisp)
  1999. {
  2000. HRESULT hres = E_OUTOFMEMORY;
  2001. CDispatchDummy* pdisp = new(CDispatchDummy);
  2002. if (pdisp)
  2003. {
  2004. hres = pdisp->QueryInterface(IID_PPV_ARG(IDispatch, ppDisp));
  2005. pdisp->Release();
  2006. }
  2007. return hres;
  2008. }
  2009. #endif
  2010. #ifdef FEATURE_FRAMES
  2011. // *** ITargetEmedding ***
  2012. HRESULT CWebBrowserOC::GetTargetFrame(ITargetFrame **ppTargetFrame)
  2013. {
  2014. if (_psb)
  2015. {
  2016. return _psb->QueryServiceItsOwn(IID_ITargetFrame2, IID_PPV_ARG(ITargetFrame, ppTargetFrame));
  2017. }
  2018. else
  2019. {
  2020. *ppTargetFrame = NULL;
  2021. return E_FAIL;
  2022. }
  2023. }
  2024. #endif
  2025. // *** CImpIConnectionPoint override ***
  2026. CConnectionPoint* CWebBrowserOC::_FindCConnectionPointNoRef(BOOL fdisp, REFIID iid)
  2027. {
  2028. CConnectionPoint *pccp;
  2029. // Warning: Some apps (MSDN for one) passes in IID_IDispatch and
  2030. // expect the ole events. So we need to be careful on which one we return.
  2031. //
  2032. if (fdisp && IsEqualIID(iid, IID_IDispatch))
  2033. {
  2034. if (_pObjectInfo->lVersion == VERSION_1)
  2035. pccp = &m_cpWB1Events;
  2036. else
  2037. pccp = &m_cpEvents;
  2038. }
  2039. else if (IsEqualIID(iid, DIID_DWebBrowserEvents2))
  2040. {
  2041. pccp = &m_cpEvents;
  2042. }
  2043. else if (IsEqualIID(iid, DIID_DWebBrowserEvents))
  2044. {
  2045. pccp = &m_cpWB1Events;
  2046. }
  2047. else if (IsEqualIID(iid, IID_IPropertyNotifySink))
  2048. {
  2049. pccp = &m_cpPropNotify;
  2050. }
  2051. else
  2052. {
  2053. pccp = NULL;
  2054. }
  2055. return pccp;
  2056. }
  2057. STDMETHODIMP CWebBrowserOC::EnumConnectionPoints(LPENUMCONNECTIONPOINTS * ppEnum)
  2058. {
  2059. return CreateInstance_IEnumConnectionPoints(ppEnum, 3,
  2060. m_cpEvents.CastToIConnectionPoint(),
  2061. m_cpWB1Events.CastToIConnectionPoint(),
  2062. m_cpPropNotify.CastToIConnectionPoint());
  2063. }
  2064. /*
  2065. ** Properties and Methods we implement
  2066. */
  2067. // Invoke perf
  2068. //
  2069. HRESULT CWebBrowserOC::Invoke(DISPID dispidMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS * pdispparams, VARIANT * pvarResult, EXCEPINFO * pexcepinfo, UINT * puArgErr)
  2070. {
  2071. HRESULT hres = S_OK;
  2072. // we should probably check that riid is IID_NULL...
  2073. _fInsideInvokeCall = TRUE; // we're inside an invoke
  2074. switch (dispidMember)
  2075. {
  2076. // handle ReadyState immediately for performance (avoid oleaut a tad longer)...
  2077. case DISPID_READYSTATE:
  2078. ASSERT(pdispparams && pdispparams->cArgs==0);
  2079. if (EVAL(pvarResult) && (wFlags & DISPATCH_PROPERTYGET))
  2080. {
  2081. ZeroMemory(pvarResult, SIZEOF(*pvarResult));
  2082. pvarResult->vt = VT_I4;
  2083. hres = get_ReadyState((READYSTATE*)(&pvarResult->lVal));
  2084. goto Cleanup;
  2085. }
  2086. break; // let the below invoke call give us the proper error value
  2087. // forward these two down to our embedded object so that
  2088. // Trident can handle cross-frame security correctly
  2089. case DISPID_SECURITYCTX:
  2090. case DISPID_SECURITYDOMAIN:
  2091. {
  2092. IDispatch* pdisp;
  2093. if (SUCCEEDED(_pautoWB2->get_Document(&pdisp)))
  2094. {
  2095. hres = pdisp->Invoke(dispidMember, riid, lcid, wFlags, pdispparams, pvarResult, pexcepinfo, puArgErr);
  2096. pdisp->Release();
  2097. goto Cleanup;
  2098. }
  2099. break;
  2100. }
  2101. default:
  2102. // handle the default after the switch.
  2103. break;
  2104. }
  2105. hres = CShellOcx::Invoke(dispidMember, riid, lcid, wFlags, pdispparams, pvarResult, pexcepinfo, puArgErr);
  2106. Cleanup:
  2107. _fInsideInvokeCall = FALSE; // We are leaving the invoke
  2108. return hres;
  2109. }
  2110. // IObjectSafety override so script can't talk to us from an unsafe zone
  2111. HRESULT CWebBrowserOC::SetInterfaceSafetyOptions(REFIID riid, DWORD dwOptionSetMask, DWORD dwEnabledOptions)
  2112. {
  2113. HRESULT hr = CObjectSafety::SetInterfaceSafetyOptions(riid, dwOptionSetMask, dwEnabledOptions);
  2114. // If we are hosted in IEXPLORER.EXE or EXPLORER.EXE (eventually this should be the default, but we need longer app-compat simmer time)
  2115. // And we can get a URL from our parent
  2116. // And the policy for that URL is "disable WebOC script access" (default for internet zone)
  2117. if (GetModuleHandle(TEXT("EXPLORER.EXE")) || GetModuleHandle(TEXT("IEXPLORE.EXE")))
  2118. {
  2119. IHTMLDocument2 *pHtmlDoc;
  2120. if (SUCCEEDED(GetHTMLDoc2(_pcli, &pHtmlDoc))) // if the parent isn't trident, then we must be client-side code hosting weboc directly - no need to bail
  2121. {
  2122. BSTR bstrURL;
  2123. if (SUCCEEDED(pHtmlDoc->get_URL(&bstrURL)))
  2124. {
  2125. DWORD dwPolicy = 0;
  2126. DWORD dwContext = 0;
  2127. ZoneCheckUrlEx(bstrURL, &dwPolicy, sizeof(dwPolicy), &dwContext, sizeof(dwContext),
  2128. URLACTION_ACTIVEX_NO_WEBOC_SCRIPT, 0, NULL);
  2129. if (GetUrlPolicyPermissions(dwPolicy) != URLPOLICY_ALLOW)
  2130. {
  2131. // Then we don't support script access - override whatever we were told above.
  2132. hr = E_ACCESSDENIED;
  2133. }
  2134. SysFreeString(bstrURL);
  2135. }
  2136. pHtmlDoc->Release();
  2137. }
  2138. }
  2139. return hr;
  2140. }
  2141. //
  2142. // Wrap around iedisp
  2143. //
  2144. #define WRAP_WB2(fn, args, nargs) \
  2145. HRESULT CWebBrowserOC :: fn args { return _pautoWB2-> fn nargs; }
  2146. #define WRAP_WB2_DESIGN(fn, args, nargs) \
  2147. HRESULT CWebBrowserOC :: fn args { if (_IsDesignMode()) return E_FAIL; else return _pautoWB2-> fn nargs; }
  2148. // IWebBrowser methods
  2149. //
  2150. WRAP_WB2_DESIGN(GoBack, (), ())
  2151. WRAP_WB2_DESIGN(GoForward, (), ())
  2152. WRAP_WB2_DESIGN(GoHome, (), ())
  2153. WRAP_WB2_DESIGN(GoSearch, (), ())
  2154. WRAP_WB2_DESIGN(Refresh, (), ())
  2155. WRAP_WB2_DESIGN(Refresh2, (VARIANT * Level), (Level))
  2156. WRAP_WB2_DESIGN(Stop, (), ())
  2157. WRAP_WB2(get_Type, (BSTR * pbstrType), (pbstrType))
  2158. WRAP_WB2(get_LocationName, (BSTR * pbstrLocationName), (pbstrLocationName))
  2159. WRAP_WB2(get_LocationURL, (BSTR * pbstrLocationURL), (pbstrLocationURL))
  2160. WRAP_WB2(get_Busy, (VARIANT_BOOL * pBool), (pBool))
  2161. HRESULT CWebBrowserOC::Navigate(BSTR URL,
  2162. VARIANT * Flags,
  2163. VARIANT * TargetFrameName,
  2164. VARIANT * PostData,
  2165. VARIANT * Headers)
  2166. {
  2167. HRESULT hr = S_OK;
  2168. if (_dwSafetyOptions)
  2169. {
  2170. hr = WrapSpecialUrl(&URL);
  2171. if (SUCCEEDED(hr))
  2172. {
  2173. if (!AccessAllowedToNamedFrame(TargetFrameName))
  2174. hr = E_ACCESSDENIED;
  2175. else
  2176. hr = _pautoWB2->Navigate(URL, Flags, TargetFrameName, PostData, Headers);
  2177. }
  2178. }
  2179. else
  2180. hr = _pautoWB2->Navigate(URL, Flags, TargetFrameName, PostData, Headers);
  2181. return hr;
  2182. }
  2183. HRESULT CWebBrowserOC::get_Application(IDispatch **ppDisp)
  2184. {
  2185. PROPMSG(TEXT("get_Application"));
  2186. return QueryInterface(IID_PPV_ARG(IDispatch, ppDisp));
  2187. }
  2188. HRESULT CWebBrowserOC::get_Parent(IDispatch **ppDisp)
  2189. {
  2190. HRESULT hres = E_FAIL;
  2191. PROPMSG(TEXT("get_Parent"));
  2192. if (ppDisp)
  2193. *ppDisp = NULL;
  2194. if (_pcli)
  2195. {
  2196. IOleContainer* pContainer;
  2197. hres = _pcli->GetContainer(&pContainer);
  2198. if (SUCCEEDED(hres))
  2199. {
  2200. hres = pContainer->QueryInterface(IID_PPV_ARG(IDispatch, ppDisp));
  2201. if (SUCCEEDED(hres) && _dwSafetyOptions)
  2202. hres = MakeSafeForScripting((IUnknown**)ppDisp);
  2203. pContainer->Release();
  2204. }
  2205. else
  2206. {
  2207. PROPMSG(TEXT("get_Parent couldn't find the container!"));
  2208. }
  2209. }
  2210. else
  2211. {
  2212. PROPMSG(TEXT("get_Parent does not have _pcli!"));
  2213. }
  2214. // if there was an error *ppDisop is NULL, and so VB realizes
  2215. // this is a "nothing" dispatch -- returning failure causes
  2216. // error boxes to appear. ugh.
  2217. return S_OK;
  2218. }
  2219. HRESULT CWebBrowserOC::get_Container(IDispatch **ppDisp)
  2220. {
  2221. // Container property is "same as parent" unless there is no parent.
  2222. // Since we always have a parent, let get_Parent handle this.
  2223. PROPMSG(TEXT("get_Containter passing off to get_Parent"));
  2224. return get_Parent(ppDisp);
  2225. }
  2226. HRESULT CWebBrowserOC::get_Document(IDispatch **ppDisp)
  2227. {
  2228. HRESULT hres = _pautoWB2->get_Document(ppDisp);
  2229. if (FAILED(hres) && ppDisp)
  2230. {
  2231. *ppDisp = NULL;
  2232. }
  2233. if (SUCCEEDED(hres) && _dwSafetyOptions)
  2234. hres = MakeSafeForScripting((IUnknown**)ppDisp);
  2235. // if there was an error *ppDisop is NULL, and so VB realizes
  2236. // this is a "nothing" dispatch -- returning failure causes
  2237. // error boxes to appear. ugh.
  2238. return S_OK;
  2239. }
  2240. HRESULT CWebBrowserOC::get_TopLevelContainer(VARIANT_BOOL * pBool)
  2241. {
  2242. PROPMSG(TEXT("get_TopLevelContainer"));
  2243. if (!pBool)
  2244. return E_INVALIDARG;
  2245. *pBool = FALSE;
  2246. return S_OK;
  2247. }
  2248. void FireEvent_OnSetWindowPos(IUnknown *punkCPContainer, DISPID dispid, long lValue)
  2249. {
  2250. VARIANTARG args[1];
  2251. IUnknown_CPContainerInvokeParam(punkCPContainer, DIID_DWebBrowserEvents2,
  2252. dispid, args, 1, VT_I4, lValue);
  2253. }
  2254. HRESULT CWebBrowserOC::get_Left(long * pl)
  2255. {
  2256. *pl = _rcPos.left;
  2257. return S_OK;
  2258. }
  2259. HRESULT CWebBrowserOC::put_Left(long Left)
  2260. {
  2261. FireEvent_OnSetWindowPos(_pautoEDS, DISPID_WINDOWSETLEFT, Left);
  2262. if (_pipsite)
  2263. {
  2264. RECT rc = _rcPos;
  2265. rc.left = Left;
  2266. return _pipsite->OnPosRectChange(&rc);
  2267. }
  2268. else
  2269. {
  2270. TraceMsg(TF_SHDCONTROL, "put_Left has no _pipsite to notify!");
  2271. return E_UNEXPECTED;
  2272. }
  2273. }
  2274. HRESULT CWebBrowserOC::get_Top(long * pl)
  2275. {
  2276. *pl = _rcPos.top;
  2277. return S_OK;
  2278. }
  2279. HRESULT CWebBrowserOC::put_Top(long Top)
  2280. {
  2281. FireEvent_OnSetWindowPos(_pautoEDS, DISPID_WINDOWSETTOP, Top);
  2282. if (_pipsite)
  2283. {
  2284. RECT rc = _rcPos;
  2285. rc.top = Top;
  2286. return(_pipsite->OnPosRectChange(&rc));
  2287. }
  2288. else
  2289. {
  2290. TraceMsg(TF_SHDCONTROL, "put_Top has no _pipsite to notify!");
  2291. return(E_UNEXPECTED);
  2292. }
  2293. }
  2294. HRESULT CWebBrowserOC::get_Width(long * pl)
  2295. {
  2296. *pl = _rcPos.right - _rcPos.left;
  2297. return S_OK;
  2298. }
  2299. HRESULT CWebBrowserOC::put_Width(long Width)
  2300. {
  2301. FireEvent_OnSetWindowPos(_pautoEDS, DISPID_WINDOWSETWIDTH, Width);
  2302. if (_pipsite)
  2303. {
  2304. RECT rc = _rcPos;
  2305. rc.right = rc.left + Width;
  2306. return(_pipsite->OnPosRectChange(&rc));
  2307. }
  2308. else
  2309. {
  2310. TraceMsg(TF_SHDCONTROL, "put_Width has no _pipsite to notify!");
  2311. return(E_UNEXPECTED);
  2312. }
  2313. }
  2314. HRESULT CWebBrowserOC::get_Height(long * pl)
  2315. {
  2316. *pl = _rcPos.bottom - _rcPos.top;
  2317. return S_OK;
  2318. }
  2319. HRESULT CWebBrowserOC::put_Height(long Height)
  2320. {
  2321. FireEvent_OnSetWindowPos(_pautoEDS, DISPID_WINDOWSETHEIGHT, Height);
  2322. if (_pipsite)
  2323. {
  2324. RECT rc = _rcPos;
  2325. rc.bottom = rc.top + Height;
  2326. return(_pipsite->OnPosRectChange(&rc));
  2327. }
  2328. else
  2329. {
  2330. TraceMsg(TF_SHDCONTROL, "put_Height has no _pipsite to notify!");
  2331. return(E_UNEXPECTED);
  2332. }
  2333. }
  2334. // IWebBrowserApp methods
  2335. //
  2336. WRAP_WB2_DESIGN(PutProperty, (BSTR szProperty, VARIANT vtValue), (szProperty, vtValue))
  2337. WRAP_WB2_DESIGN(GetProperty, (BSTR szProperty, VARIANT * pvtValue), (szProperty, pvtValue))
  2338. WRAP_WB2(get_FullName, (BSTR * pbstrFullName), (pbstrFullName))
  2339. WRAP_WB2(get_Path, (BSTR * pbstrPath), (pbstrPath))
  2340. HRESULT CWebBrowserOC::Quit()
  2341. {
  2342. return E_FAIL;
  2343. }
  2344. HRESULT CWebBrowserOC::ClientToWindow(int * pcx, int * pcy)
  2345. {
  2346. LONG lX = *pcx, lY = *pcy;
  2347. VARIANTARG args[2];
  2348. IUnknown_CPContainerInvokeParam(_pautoEDS, DIID_DWebBrowserEvents2,
  2349. DISPID_CLIENTTOHOSTWINDOW, args, 2,
  2350. VT_I4 | VT_BYREF, &lX,
  2351. VT_I4 | VT_BYREF, &lY);
  2352. *pcx = lX;
  2353. *pcy = lY;
  2354. return S_OK;
  2355. }
  2356. HRESULT CWebBrowserOC::get_Name(BSTR * pbstrName)
  2357. {
  2358. *pbstrName = LoadBSTR(IDS_SHELLEXPLORER);
  2359. return *pbstrName ? S_OK : E_OUTOFMEMORY;
  2360. }
  2361. HRESULT CWebBrowserOC::get_HWND(LONG_PTR * pHWND)
  2362. {
  2363. *pHWND = NULL;
  2364. return E_FAIL;
  2365. }
  2366. HRESULT CWebBrowserOC::get_FullScreen(VARIANT_BOOL * pBool)
  2367. {
  2368. *pBool = BOOL_TO_VARIANTBOOL(_fFullScreen);
  2369. return S_OK;
  2370. }
  2371. HRESULT CWebBrowserOC::put_FullScreen(VARIANT_BOOL Value)
  2372. {
  2373. _fFullScreen = VARIANTBOOL_TO_BOOL(Value);
  2374. FireEvent_OnAdornment(_pautoEDS, DISPID_ONFULLSCREEN, Value);
  2375. return S_OK;
  2376. }
  2377. HRESULT CWebBrowserOC::get_Visible(VARIANT_BOOL * pBool)
  2378. {
  2379. *pBool = BOOL_TO_VARIANTBOOL(_fVisible);
  2380. return S_OK;
  2381. }
  2382. HRESULT CWebBrowserOC::put_Visible(VARIANT_BOOL Value)
  2383. {
  2384. _fVisible = VARIANTBOOL_TO_BOOL(Value);
  2385. FireEvent_OnAdornment(_pautoEDS, DISPID_ONVISIBLE, Value);
  2386. return S_OK;
  2387. }
  2388. HRESULT CWebBrowserOC::get_StatusBar(VARIANT_BOOL * pBool)
  2389. {
  2390. *pBool = BOOL_TO_VARIANTBOOL(!_fNoStatusBar);
  2391. return S_OK;
  2392. }
  2393. HRESULT CWebBrowserOC::put_StatusBar(VARIANT_BOOL Value)
  2394. {
  2395. _fNoStatusBar = !VARIANTBOOL_TO_BOOL(Value);
  2396. FireEvent_OnAdornment(_pautoEDS, DISPID_ONSTATUSBAR, Value);
  2397. return S_OK;
  2398. }
  2399. HRESULT CWebBrowserOC::get_StatusText(BSTR * pbstr)
  2400. {
  2401. *pbstr = NULL;
  2402. return E_FAIL;
  2403. }
  2404. HRESULT CWebBrowserOC::put_StatusText(BSTR bstr)
  2405. {
  2406. return E_FAIL;
  2407. }
  2408. HRESULT CWebBrowserOC::get_ToolBar(int * pBool)
  2409. {
  2410. // BOGUS: variant values for int type
  2411. *pBool = (!_fNoToolBar) ? VARIANT_TRUE : VARIANT_FALSE;
  2412. return S_OK;
  2413. }
  2414. HRESULT CWebBrowserOC::put_ToolBar(int iToolbar)
  2415. {
  2416. _fNoToolBar = (!iToolbar) ? TRUE : FALSE;
  2417. FireEvent_OnAdornment(_pautoEDS, DISPID_ONTOOLBAR, iToolbar);
  2418. return S_OK;
  2419. }
  2420. HRESULT CWebBrowserOC::get_MenuBar(VARIANT_BOOL * pvbMenuBar)
  2421. {
  2422. *pvbMenuBar = BOOL_TO_VARIANTBOOL(!_fNoMenuBar);
  2423. return S_OK;
  2424. }
  2425. HRESULT CWebBrowserOC::put_MenuBar(VARIANT_BOOL vbMenuBar)
  2426. {
  2427. _fNoMenuBar = !VARIANTBOOL_TO_BOOL(vbMenuBar);
  2428. FireEvent_OnAdornment(_pautoEDS, DISPID_ONMENUBAR, vbMenuBar);
  2429. return S_OK;
  2430. }
  2431. HRESULT CWebBrowserOC::get_AddressBar(VARIANT_BOOL * pvbAddressBar)
  2432. {
  2433. *pvbAddressBar = BOOL_TO_VARIANTBOOL(!_fNoAddressBar);
  2434. return S_OK;
  2435. }
  2436. HRESULT CWebBrowserOC::put_AddressBar(VARIANT_BOOL vbAddressBar)
  2437. {
  2438. _fNoAddressBar = !VARIANTBOOL_TO_BOOL(vbAddressBar);
  2439. FireEvent_OnAdornment(_pautoEDS, DISPID_ONADDRESSBAR, vbAddressBar);
  2440. return S_OK;
  2441. }
  2442. HRESULT CWebBrowserOC::put_Resizable(VARIANT_BOOL vbResizable)
  2443. {
  2444. FireEvent_OnAdornment(_pautoEDS, DISPID_WINDOWSETRESIZABLE, vbResizable);
  2445. return S_OK;
  2446. }
  2447. // IWebBrowser2 methods
  2448. //
  2449. WRAP_WB2_DESIGN(QueryStatusWB, (OLECMDID cmdID, OLECMDF * pcmdf), (cmdID, pcmdf))
  2450. WRAP_WB2_DESIGN(ShowBrowserBar, (VARIANT * pvaClsid, VARIANT * pvaShow, VARIANT * pvaSize), (pvaClsid, pvaShow, pvaSize))
  2451. WRAP_WB2(get_ReadyState, (READYSTATE * plReadyState), (plReadyState))
  2452. WRAP_WB2(get_RegisterAsDropTarget, (VARIANT_BOOL * pbRegister), (pbRegister))
  2453. WRAP_WB2(put_RegisterAsDropTarget, (VARIANT_BOOL bRegister), (bRegister))
  2454. WRAP_WB2(get_Offline, (VARIANT_BOOL * pbOffline), (pbOffline))
  2455. WRAP_WB2(put_Offline, (VARIANT_BOOL bOffline), (bOffline))
  2456. WRAP_WB2(get_Silent, (VARIANT_BOOL * pbSilent), (pbSilent))
  2457. WRAP_WB2(put_Silent, (VARIANT_BOOL bSilent), (bSilent))
  2458. HRESULT
  2459. CWebBrowserOC::Navigate2(VARIANT * URL,
  2460. VARIANT * Flags,
  2461. VARIANT * TargetFrameName,
  2462. VARIANT * PostData,
  2463. VARIANT * Headers)
  2464. {
  2465. HRESULT hr = S_OK;
  2466. if (_dwSafetyOptions && ((WORD)VT_BSTR == URL->vt) && URL->bstrVal)
  2467. {
  2468. hr = WrapSpecialUrl(&URL->bstrVal);
  2469. if (SUCCEEDED(hr))
  2470. {
  2471. if (!AccessAllowedToNamedFrame(TargetFrameName))
  2472. hr = E_ACCESSDENIED;
  2473. else
  2474. hr = _pautoWB2->Navigate2(URL, Flags, TargetFrameName, PostData, Headers);
  2475. }
  2476. }
  2477. else
  2478. hr = _pautoWB2->Navigate2(URL, Flags, TargetFrameName, PostData, Headers);
  2479. return hr;
  2480. }
  2481. HRESULT CWebBrowserOC::ExecWB(OLECMDID cmdID, OLECMDEXECOPT cmdexecopt,
  2482. VARIANT * pvaIn, VARIANT * pvaOut)
  2483. {
  2484. HRESULT hr = E_FAIL;
  2485. if ( !_IsDesignMode() )
  2486. {
  2487. // do not process print preview commands given from script for security reasons
  2488. // Ferhane IE60 Bug#16693
  2489. // Print templates have extra privelages.
  2490. // Print/Preview allows you to specify a custom print template URL as a BSTR or in a safearray.
  2491. // This is a security hole if available from script. Disallow it.
  2492. if ( _fInsideInvokeCall
  2493. && ( cmdID == OLECMDID_PRINTPREVIEW
  2494. || cmdID == OLECMDID_PRINT)
  2495. && pvaIn
  2496. && ( V_VT(pvaIn) == VT_BSTR
  2497. || V_VT(pvaIn) == VT_ARRAY)
  2498. )
  2499. {
  2500. return E_ACCESSDENIED; // More meaningful than E_FAIL
  2501. }
  2502. // if _dwSafetyOptions are set then we are suppossed to be
  2503. // running in secure mode. This means the UI-less printing should NOT
  2504. // be honored. This is a security issue, see ie bug 23620.
  2505. // otherwise just let the call go through
  2506. if ((cmdID == OLECMDID_PRINT) && _dwSafetyOptions)
  2507. {
  2508. // so if the UI-less- request flag is set we need to unset it.
  2509. if (cmdexecopt == OLECMDEXECOPT_DONTPROMPTUSER)
  2510. cmdexecopt = OLECMDEXECOPT_DODEFAULT;
  2511. }
  2512. // If the optional argument pvargin is not specified make it VT_EMPTY.
  2513. if (pvaIn && (V_VT(pvaIn) == VT_ERROR) && (V_ERROR(pvaIn) == DISP_E_PARAMNOTFOUND))
  2514. {
  2515. V_VT(pvaIn) = VT_EMPTY;
  2516. V_I4(pvaIn) = 0;
  2517. }
  2518. // If the optional argument pvargin is not specified make it VT_EMPTY.
  2519. if (pvaOut && (V_VT(pvaOut) == VT_ERROR) && (V_ERROR(pvaOut) == DISP_E_PARAMNOTFOUND))
  2520. {
  2521. V_VT(pvaOut) = VT_EMPTY;
  2522. V_I4(pvaOut) = 0;
  2523. }
  2524. if ( cmdID == OLECMDID_PASTE
  2525. || cmdID == OLECMDID_COPY
  2526. || cmdID == OLECMDID_CUT)
  2527. {
  2528. BSTR bstrUrl;
  2529. if (_dwSafetyOptions)
  2530. return S_OK;
  2531. if (SUCCEEDED(get_LocationURL(&bstrUrl)))
  2532. {
  2533. DWORD dwPolicy = 0;
  2534. DWORD dwContext = 0;
  2535. ZoneCheckUrlEx(bstrUrl, &dwPolicy, SIZEOF(dwPolicy), &dwContext, SIZEOF(dwContext),
  2536. URLACTION_SCRIPT_PASTE, 0, NULL);
  2537. SysFreeString(bstrUrl);
  2538. if (GetUrlPolicyPermissions(dwPolicy) != URLPOLICY_ALLOW)
  2539. return S_OK;
  2540. }
  2541. }
  2542. // now pass along the call
  2543. hr = _pautoWB2->ExecWB(cmdID, cmdexecopt, pvaIn, pvaOut);
  2544. }
  2545. return hr;
  2546. }
  2547. HRESULT CWebBrowserOC::get_RegisterAsBrowser(VARIANT_BOOL * pbRegister)
  2548. {
  2549. *pbRegister = BOOL_TO_VARIANTBOOL(_fShouldRegisterAsBrowser);
  2550. return S_OK;
  2551. }
  2552. HRESULT CWebBrowserOC::put_RegisterAsBrowser(VARIANT_BOOL bRegister)
  2553. {
  2554. _fShouldRegisterAsBrowser = VARIANTBOOL_TO_BOOL(bRegister);
  2555. if (bRegister)
  2556. _RegisterWindow();
  2557. else
  2558. _UnregisterWindow();
  2559. return S_OK;
  2560. }
  2561. HRESULT CWebBrowserOC::get_TheaterMode(VARIANT_BOOL * pvbTheaterMode)
  2562. {
  2563. *pvbTheaterMode = BOOL_TO_VARIANTBOOL(_fTheaterMode);
  2564. return S_OK;
  2565. }
  2566. HRESULT CWebBrowserOC::put_TheaterMode(VARIANT_BOOL Value)
  2567. {
  2568. _fTheaterMode = VARIANTBOOL_TO_BOOL(Value);
  2569. FireEvent_OnAdornment(_pautoEDS, DISPID_ONTHEATERMODE, Value);
  2570. return S_OK;
  2571. }
  2572. // IExpDispSupport
  2573. //
  2574. HRESULT CWebBrowserOC::OnTranslateAccelerator(MSG *pMsg,DWORD grfModifiers)
  2575. {
  2576. return IUnknown_TranslateAcceleratorOCS(_pcli, pMsg, grfModifiers);
  2577. }
  2578. HRESULT CWebBrowserOC::OnInvoke(DISPID dispidMember, REFIID iid, LCID lcid, WORD wFlags, DISPPARAMS * pdispparams,
  2579. VARIANT * pVarResult, EXCEPINFO * pexcepinfo, UINT * puArgErr)
  2580. {
  2581. // We get first crack at this
  2582. HRESULT hres = _pautoEDS->OnInvoke(dispidMember, iid, lcid, wFlags, pdispparams, pVarResult,pexcepinfo,puArgErr);
  2583. // let the container get second crack at ambient properties
  2584. //
  2585. if (FAILED(hres))
  2586. {
  2587. if (!_pDispAmbient)
  2588. {
  2589. if (_pcli)
  2590. _pcli->QueryInterface(IID_PPV_ARG(IDispatch, &_pDispAmbient));
  2591. }
  2592. if (_pDispAmbient)
  2593. {
  2594. hres = _pDispAmbient->Invoke(dispidMember, iid, lcid, wFlags, pdispparams, pVarResult,pexcepinfo,puArgErr);
  2595. }
  2596. }
  2597. return hres;
  2598. }
  2599. // IExpDispSupportOC
  2600. //
  2601. HRESULT CWebBrowserOC::OnOnControlInfoChanged()
  2602. {
  2603. HRESULT hres = E_NOTIMPL;
  2604. if (_pcli)
  2605. {
  2606. IOleControlSite* pocs;
  2607. if (SUCCEEDED(_pcli->QueryInterface(IID_PPV_ARG(IOleControlSite, &pocs))))
  2608. {
  2609. hres = pocs->OnControlInfoChanged();
  2610. pocs->Release();
  2611. }
  2612. }
  2613. return hres;
  2614. }
  2615. HRESULT CWebBrowserOC::GetDoVerbMSG(MSG *pMsg)
  2616. {
  2617. if (_pmsgDoVerb)
  2618. {
  2619. *pMsg = *_pmsgDoVerb;
  2620. return S_OK;
  2621. }
  2622. return E_FAIL;
  2623. }
  2624. HRESULT CWebBrowserOC::LoadHistory(IStream *pstm, IBindCtx *pbc)
  2625. {
  2626. _InitDefault();
  2627. ASSERT(_psb);
  2628. HRESULT hr = E_FAIL;
  2629. if (_psb)
  2630. {
  2631. hr = _psb->LoadHistory(pstm, pbc);
  2632. _OnLoaded(FAILED(hr));
  2633. TraceMsg(TF_TRAVELLOG, "WBOC::LoadHistory pstm = %x, pbc = %x, hr = %x", pstm, pbc, hr);
  2634. }
  2635. return hr;
  2636. }
  2637. HRESULT CWebBrowserOC::SaveHistory(IStream *pstm)
  2638. {
  2639. ASSERT(_psb);
  2640. TraceMsg(TF_TRAVELLOG, "WBOC::SaveHistory calling psb->SaveHistory");
  2641. return _psb ? _psb->SaveHistory(pstm) : E_FAIL;
  2642. }
  2643. HRESULT CWebBrowserOC::SetPositionCookie(DWORD dw)
  2644. {
  2645. ASSERT(_psb);
  2646. TraceMsg(TF_TRAVELLOG, "WBOC::SetPositionCookie calling psb->GetPositionCookie");
  2647. return _psb ? _psb->SetPositionCookie(dw) : E_FAIL;
  2648. }
  2649. HRESULT CWebBrowserOC::GetPositionCookie(DWORD *pdw)
  2650. {
  2651. ASSERT(_psb);
  2652. TraceMsg(TF_TRAVELLOG, "WBOC::GetPositionCookie calling psb->GetPositionCookie");
  2653. return _psb ? _psb->GetPositionCookie(pdw) : E_FAIL;
  2654. }
  2655. HMODULE CWebBrowserOC::_GetBrowseUI()
  2656. {
  2657. if (_hBrowseUI == HMODULE_NOTLOADED)
  2658. {
  2659. _hBrowseUI = LoadLibrary(TEXT("browseui.dll"));
  2660. }
  2661. return _hBrowseUI;
  2662. }
  2663. BOOL CWebBrowserOC::AccessAllowedToNamedFrame(VARIANT *varTargetFrameName)
  2664. {
  2665. BOOL fAllowed = TRUE;
  2666. HRESULT hr = S_OK;
  2667. ITargetFrame2 * pTopTargetFrame = NULL;
  2668. IUnknown * punkTargetFrame = NULL;
  2669. IWebBrowser2 * pIWB2Target = NULL;
  2670. BSTR bstrTargetUrl = NULL;
  2671. BSTR bstrSrcUrl = NULL;
  2672. if (varTargetFrameName && ((WORD)VT_BSTR == varTargetFrameName->vt) && varTargetFrameName->bstrVal)
  2673. {
  2674. IEFrameAuto * piefa = NULL;
  2675. hr = _pauto->QueryInterface(IID_PPV_ARG(IEFrameAuto, &piefa));
  2676. if (SUCCEEDED(hr))
  2677. {
  2678. hr = TargetQueryService((IShellBrowser *)piefa, IID_PPV_ARG(ITargetFrame2, &pTopTargetFrame));
  2679. if (SUCCEEDED(hr))
  2680. {
  2681. hr = pTopTargetFrame->FindFrame(
  2682. varTargetFrameName->bstrVal,
  2683. FINDFRAME_JUSTTESTEXISTENCE,
  2684. &punkTargetFrame);
  2685. if (SUCCEEDED(hr) && punkTargetFrame)
  2686. {
  2687. // yes, we found a frame with that name. QI for the automation
  2688. // interface on that frame.
  2689. hr = punkTargetFrame->QueryInterface(IID_PPV_ARG(IWebBrowser2, &pIWB2Target));
  2690. if (SUCCEEDED(hr))
  2691. {
  2692. hr = pIWB2Target->get_LocationURL(&bstrTargetUrl);
  2693. if (SUCCEEDED(hr))
  2694. {
  2695. hr = _pautoWB2->get_LocationURL(&bstrSrcUrl);
  2696. if (SUCCEEDED(hr))
  2697. {
  2698. fAllowed = AccessAllowed(bstrSrcUrl, bstrTargetUrl);
  2699. SysFreeString(bstrSrcUrl);
  2700. }
  2701. SysFreeString(bstrTargetUrl);
  2702. }
  2703. pIWB2Target->Release();
  2704. }
  2705. punkTargetFrame->Release();
  2706. }
  2707. pTopTargetFrame->Release();
  2708. }
  2709. piefa->Release();
  2710. }
  2711. }
  2712. return fAllowed;
  2713. }
  2714. // The SECURELOCK enumeration must be sorted in order of security level, and we may
  2715. // need to insert new values into the middle of the list in future. So we'll map
  2716. // the values to a set of constants.
  2717. BOOL SecureLockToIconConstant(int nSecureLock, LONG *plIconConstant)
  2718. {
  2719. BOOL fRet = TRUE;
  2720. switch (nSecureLock)
  2721. {
  2722. case SECURELOCK_SET_UNSECURE : *plIconConstant = secureLockIconUnsecure; break;
  2723. case SECURELOCK_SET_MIXED : *plIconConstant = secureLockIconMixed; break;
  2724. case SECURELOCK_SET_SECUREUNKNOWNBIT : *plIconConstant = secureLockIconSecureUnknownBits; break;
  2725. case SECURELOCK_SET_SECURE40BIT : *plIconConstant = secureLockIconSecure40Bit; break;
  2726. case SECURELOCK_SET_SECURE56BIT : *plIconConstant = secureLockIconSecure56Bit; break;
  2727. case SECURELOCK_SET_SECURE128BIT : *plIconConstant = secureLockIconSecure128Bit; break;
  2728. case SECURELOCK_SET_FORTEZZA : *plIconConstant = secureLockIconSecureFortezza; break;
  2729. default:
  2730. // Don't need to fire an event
  2731. fRet = FALSE;
  2732. }
  2733. return fRet;
  2734. }
  2735. void CWebBrowserOC::_OnSetSecureLockIcon(int lock)
  2736. {
  2737. LONG lIconConstant;
  2738. if (SecureLockToIconConstant(lock, &lIconConstant))
  2739. {
  2740. // Fire the OnUpdateSecurityIcon event only from the DWebBrowserEvents2 connection point
  2741. VARIANTARG args[1];
  2742. IUnknown_CPContainerInvokeParam(_pautoEDS, DIID_DWebBrowserEvents2,
  2743. DISPID_SETSECURELOCKICON, args, 1, VT_I4, lIconConstant);
  2744. }
  2745. }
  2746. // CWebBrowserSB implementation
  2747. CWebBrowserSB::CWebBrowserSB(IUnknown* pauto, CWebBrowserOC* psvo)
  2748. : CBASEBROWSER(NULL)
  2749. , _psvo(psvo)
  2750. {
  2751. _Initialize(0, pauto);
  2752. }
  2753. CWebBrowserSB::~CWebBrowserSB()
  2754. {
  2755. }
  2756. HRESULT CWebBrowserSB::QueryInterface(REFIID riid, void ** ppvObj)
  2757. {
  2758. HRESULT hr = CBASEBROWSER::QueryInterface(riid, ppvObj);
  2759. if (FAILED(hr) && (riid == IID_IIsWebBrowserSB))
  2760. hr = CBASEBROWSER::QueryInterface(IID_IUnknown, ppvObj);
  2761. return hr;
  2762. }
  2763. BOOL VirtualTopLevelBrowser(IOleClientSite * pcls)
  2764. {
  2765. IOleContainer * poc;
  2766. BOOL fNonStandard = FALSE;
  2767. if (SUCCEEDED(pcls->GetContainer(&poc)))
  2768. {
  2769. ITargetContainer * ptc;
  2770. // Is our container hosting us?
  2771. if (SUCCEEDED(poc->QueryInterface(IID_PPV_ARG(ITargetContainer, &ptc))))
  2772. {
  2773. fNonStandard = TRUE;
  2774. ptc->Release();
  2775. }
  2776. poc->Release();
  2777. }
  2778. return fNonStandard;
  2779. }
  2780. HRESULT CWebBrowserSB::SetTopBrowser()
  2781. {
  2782. HRESULT hres = CBASEBROWSER::SetTopBrowser();
  2783. if (_fTopBrowser && EVAL(_psvo))
  2784. _fNoTopLevelBrowser = VirtualTopLevelBrowser(_psvo->_pcli);
  2785. return hres;
  2786. }
  2787. LRESULT CWebBrowserSB::WndProcBS(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  2788. {
  2789. LRESULT lret = CBASEBROWSER::WndProcBS(hwnd, uMsg, wParam, lParam);
  2790. switch(uMsg)
  2791. {
  2792. case WM_DESTROY:
  2793. // Because we won't get WM_NCDESTROY here, we should clean up
  2794. // this member variable here.
  2795. _bbd._hwnd = NULL;
  2796. break;
  2797. }
  2798. return lret;
  2799. }
  2800. // *** IOleWindow methods ***
  2801. // CBASEBROWSER maps SetStatusTextSB to SendControlMsg,
  2802. // so we don't need a CWebBrowserSB::SetStatusTextSB implementation.
  2803. HRESULT CWebBrowserSB::_EnableModeless(BOOL fEnable, BOOL fDirection)
  2804. {
  2805. HRESULT hres = S_OK;
  2806. CBASEBROWSER::EnableModelessSB(fEnable);
  2807. if (fDirection == DIRECTION_FORWARD_TO_PARENT)
  2808. {
  2809. if (_psvo && _psvo->_pipframe)
  2810. {
  2811. hres = _psvo->_pipframe->EnableModeless(fEnable);
  2812. if (!fEnable && _psvo->_fHostedInVB5)
  2813. {
  2814. // APPHACK: VB5 -- If we haven't put up a dialog between the EnableModelessSB(FALSE) call and this
  2815. // call, we'll end up with a message on the queue that will disable all windows.
  2816. // Let's peek for this message and dispatch it if it is VB5's.
  2817. //
  2818. #define VBM_POSTENABLEMODELESS 0x1006
  2819. #define VBM_MAINCLASS1 TEXT("ThunderRT5Main")
  2820. #define VBM_MAINCLASS2 TEXT("ThunderRT6Main")
  2821. #define VBM_MAINCLASS3 TEXT("ThunderMain")
  2822. MSG msg;
  2823. HWND hwnd = NULL;
  2824. TCHAR strBuf[15];
  2825. if (PeekMessage( &msg, NULL, VBM_POSTENABLEMODELESS, VBM_POSTENABLEMODELESS, PM_NOREMOVE))
  2826. {
  2827. /* On Win95, apparently PeekMessage can return one type of message
  2828. * outside the range specified: WM_QUIT. Double-check the message we
  2829. * got back.
  2830. */
  2831. if (msg.message == VBM_POSTENABLEMODELESS)
  2832. {
  2833. GetClassName(msg.hwnd, strBuf, sizeof(strBuf));
  2834. if (StrCmp(strBuf, VBM_MAINCLASS1) == 0 ||
  2835. StrCmp(strBuf, VBM_MAINCLASS2) == 0 ||
  2836. StrCmp(strBuf, VBM_MAINCLASS3) == 0)
  2837. {
  2838. PeekMessage( &msg, msg.hwnd, VBM_POSTENABLEMODELESS, VBM_POSTENABLEMODELESS, PM_REMOVE);
  2839. TraceMsg(TF_SHDCONTROL, "shv CWebBrowserSB::_EnableModeless dispatching VBM_POSTENABLEMODELESS" );
  2840. DispatchMessage(&msg);
  2841. }
  2842. }
  2843. }
  2844. }
  2845. else
  2846. {
  2847. // If we're a subframe
  2848. // AND the EnableModeless(FALSE) count (_cRefCannotNavigate) has become zero
  2849. // AND our window is disabled
  2850. // THEN the likely scenario is that VB5 failed to reenable us. Trace it and reenable
  2851. // ourselves.
  2852. //
  2853. if (!_fTopBrowser
  2854. && _cRefCannotNavigate == 0
  2855. && GetWindowLong(_bbd._hwnd, GWL_STYLE) & WS_DISABLED)
  2856. {
  2857. TraceMsg(TF_WARNING, "shv Subframe was left disabled. Reenabling ourselves.");
  2858. EnableWindow(_bbd._hwnd, TRUE);
  2859. }
  2860. }
  2861. }
  2862. else if (_psvo && _psvo->_pcli)
  2863. {
  2864. IShellBrowser* psbParent;
  2865. if (SUCCEEDED(IUnknown_QueryService(_psvo->_pcli, SID_SShellBrowser, IID_PPV_ARG(IShellBrowser, &psbParent))))
  2866. {
  2867. psbParent->EnableModelessSB(fEnable);
  2868. psbParent->Release();
  2869. }
  2870. }
  2871. else
  2872. {
  2873. IOIPAMSG(TEXT("_EnableModeless NOT forwarding on to _pipframe"));
  2874. }
  2875. }
  2876. else // DIRECTION_FORWARD_TO_CHILD
  2877. {
  2878. ASSERT(fDirection == DIRECTION_FORWARD_TO_CHILD);
  2879. if (_bbd._psv)
  2880. {
  2881. hres = _bbd._psv->EnableModelessSV(fEnable);
  2882. }
  2883. else
  2884. {
  2885. IOIPAMSG(TEXT("_EnableModeless NOT forwarding on to _psv"));
  2886. }
  2887. }
  2888. return hres;
  2889. }
  2890. HRESULT CWebBrowserSB::EnableModelessSB(BOOL fEnable)
  2891. {
  2892. return _EnableModeless(fEnable, DIRECTION_FORWARD_TO_PARENT);
  2893. }
  2894. HRESULT CWebBrowserSB::_TranslateAccelerator(LPMSG lpmsg, WORD wID, BOOL fDirection)
  2895. {
  2896. // see if we handle it
  2897. HRESULT hr = CBASEBROWSER::TranslateAcceleratorSB(lpmsg, wID);
  2898. if (hr == S_OK)
  2899. {
  2900. IOIPAMSG(TEXT("_TranslateAccelerator: CBASEBROWSER's TranslateAcceleratorSB handled it"));
  2901. }
  2902. else if (fDirection == DIRECTION_FORWARD_TO_PARENT)
  2903. {
  2904. if (_psvo && _psvo->_pipframe)
  2905. {
  2906. hr = _psvo->_pipframe->TranslateAccelerator(lpmsg, wID);
  2907. }
  2908. else
  2909. {
  2910. IOIPAMSG(TEXT("_TranslateAccelerator NOT forwarding on to _pipframe"));
  2911. hr = S_FALSE;
  2912. }
  2913. }
  2914. else // fDirection == DIRECTION_FORWARD_TO_CHILD
  2915. {
  2916. if (_bbd._psv)
  2917. {
  2918. hr = _bbd._psv->TranslateAccelerator(lpmsg);
  2919. }
  2920. else
  2921. {
  2922. IOIPAMSG(TEXT("_TranslateAccelerator NOT forwarding on to _psv"));
  2923. hr = S_FALSE;
  2924. }
  2925. }
  2926. return hr;
  2927. }
  2928. HRESULT CWebBrowserSB::TranslateAcceleratorSB(LPMSG lpmsg, WORD wID)
  2929. {
  2930. return _TranslateAccelerator(lpmsg, wID, DIRECTION_FORWARD_TO_PARENT);
  2931. }
  2932. HRESULT CWebBrowserSB::SendControlMsg(UINT id, UINT uMsg, WPARAM wParam,
  2933. LPARAM lParam, LRESULT * pret)
  2934. {
  2935. // let CBASEBROWSER try first so we get automation notifications working
  2936. HRESULT hres = CBASEBROWSER::SendControlMsg(id, uMsg, wParam, lParam, pret);
  2937. // if we're in a blocking frame, our GetControlWindow above will fail
  2938. // causing CBASEBROWSER to fail. try to map to an IOleInPlaceFrame call.
  2939. if (FAILED(hres) && _psvo)
  2940. {
  2941. // forward status bar text changes to the frame.
  2942. if ((id == FCW_STATUS) &&
  2943. (uMsg == SB_SETTEXT || uMsg == SB_SETTEXTW) && // trying to set status text
  2944. (!(wParam & SBT_OWNERDRAW)) && // we don't own the window -- this can't work
  2945. (((wParam & 0x00FF) == 0x00FF) || ((wParam & 0x00FF)== 0))) // simple or 0th item
  2946. {
  2947. WCHAR szStatusText[256];
  2948. if (uMsg == SB_SETTEXT) {
  2949. if (lParam)
  2950. {
  2951. SHTCharToUnicode((LPTSTR)lParam, szStatusText, ARRAYSIZE(szStatusText));
  2952. }
  2953. else
  2954. {
  2955. szStatusText[0] = L'\0';
  2956. }
  2957. lParam = (LPARAM) szStatusText;
  2958. }
  2959. else if (!lParam)
  2960. {
  2961. // uMsg == SB_SETTEXTW
  2962. // Found a container that doesn't like null string pointers. Pass an empty string instead.
  2963. // (IE v 4.1 bug 64629)
  2964. szStatusText[0] = 0;
  2965. lParam = (LPARAM) szStatusText;
  2966. }
  2967. if (_psvo->_pipframe)
  2968. {
  2969. if (pret)
  2970. {
  2971. *pret = 0;
  2972. }
  2973. hres = _psvo->_pipframe->SetStatusText((LPCOLESTR)lParam);
  2974. }
  2975. else
  2976. {
  2977. IOIPAMSG(TEXT("SetStatusTextSB NOT forwarding on to _pipframe"));
  2978. }
  2979. }
  2980. }
  2981. return hres;
  2982. }
  2983. HRESULT CWebBrowserSB::OnViewWindowActive(struct IShellView * psv)
  2984. {
  2985. if (_psvo)
  2986. {
  2987. // The view is notifying us that it just went UIActive,
  2988. // we need to update our state. OC_UIACTIVE normally
  2989. // tells the view to UIActivate itself, but in this case
  2990. // it already is. Avoid an infinite loop and pass FALSE.
  2991. _psvo->_DoActivateChange(NULL, OC_UIACTIVE, FALSE);
  2992. }
  2993. return CBASEBROWSER::OnViewWindowActive(psv);
  2994. }
  2995. LRESULT CWebBrowserSB::_DefWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  2996. {
  2997. // explicitly do nothing...
  2998. // this is just to override CBASEBROWSER's _DefWindowProc.
  2999. return 0;
  3000. }
  3001. void CWebBrowserSB::_ViewChange(DWORD dwAspect, LONG lindex)
  3002. {
  3003. //
  3004. // forward this notify up to the OC's OBJECTCODE_VIEWCHANGE handler so it
  3005. // gets forwarded on to our container.
  3006. //
  3007. if (_psvo)
  3008. _psvo->_ViewChange(dwAspect, lindex);
  3009. //
  3010. // also let the base browser handle this view change in case nobody else is
  3011. // handling palette messages. most of the time this will be a nop but in
  3012. // the case where a WM_QUERYNEWPALETTE makes it down to us this will allow
  3013. // us to manage the palette properly.
  3014. //
  3015. CBASEBROWSER::_ViewChange(dwAspect, lindex);
  3016. }
  3017. HRESULT CWebBrowserSB::ActivatePendingView()
  3018. {
  3019. CVOCBMSG(TEXT("_ActivatePendingView"));
  3020. // CBASEBROWSER::_ActivatePendingView will send a NavigateComplete
  3021. // event. During this event our parent may destroy us. We then fault
  3022. // dereferencing _psvo below. So we need to wrap this function with
  3023. // an AddRef/Release. (bug 15424)
  3024. //
  3025. AddRef();
  3026. HRESULT hres = CBASEBROWSER::ActivatePendingView();
  3027. if (SUCCEEDED(hres) && _psvo)
  3028. _psvo->_OnSetShellView(_bbd._psv);
  3029. Release();
  3030. return hres;
  3031. }
  3032. HRESULT CWebBrowserSB::ReleaseShellView(void)
  3033. {
  3034. CVOCBMSG(TEXT("_ReleaseShellView"));
  3035. if (_psvo)
  3036. _psvo->_OnReleaseShellView();
  3037. return CBASEBROWSER::ReleaseShellView();
  3038. }
  3039. /// IBrowserService stuff
  3040. HRESULT CWebBrowserSB::GetParentSite(struct IOleInPlaceSite** ppipsite)
  3041. {
  3042. HRESULT hres = E_FAIL; // assume error
  3043. *ppipsite = NULL; // assume error
  3044. if (_psvo)
  3045. {
  3046. if (_psvo->_pipsite)
  3047. {
  3048. *ppipsite = _psvo->_pipsite;
  3049. _psvo->_pipsite->AddRef();
  3050. hres = S_OK;
  3051. }
  3052. else if (_psvo->_pcli)
  3053. {
  3054. hres = _psvo->_pcli->QueryInterface(IID_PPV_ARG(IOleInPlaceSite, ppipsite));
  3055. }
  3056. else
  3057. {
  3058. // Is it expected?
  3059. TraceMsg(DM_WARNING, "CWBSB::GetParentSite called when _pcli is NULL");
  3060. }
  3061. }
  3062. return hres;
  3063. }
  3064. #ifdef FEATURE_FRAMES
  3065. HRESULT CWebBrowserSB::GetOleObject(struct IOleObject** ppobjv)
  3066. {
  3067. if (_psvo == NULL)
  3068. {
  3069. *ppobjv = NULL;
  3070. return E_FAIL;
  3071. }
  3072. return _psvo->QueryInterface(IID_PPV_ARG(IOleObject, ppobjv));
  3073. }
  3074. #endif
  3075. HRESULT CWebBrowserSB::SetNavigateState(BNSTATE bnstate)
  3076. {
  3077. // Do our own things (such as firing events and update _fNavigate).
  3078. HRESULT hres = CBASEBROWSER::SetNavigateState(bnstate);
  3079. //
  3080. // Then, tell the container to update the download state.
  3081. // This will start the animation if this OC is either in a frameset
  3082. // or in a browser band.
  3083. //
  3084. VARIANTARG var;
  3085. var.vt = VT_I4;
  3086. var.lVal = _fNavigate;
  3087. Exec(NULL, OLECMDID_SETDOWNLOADSTATE, 0, &var, NULL);
  3088. return hres;
  3089. }
  3090. LRESULT CWebBrowserSB::OnNotify(LPNMHDR pnm)
  3091. {
  3092. switch(pnm->code)
  3093. {
  3094. case SEN_DDEEXECUTE:
  3095. {
  3096. IShellBrowser *psbTop;
  3097. if (pnm->idFrom == 0 && SUCCEEDED(_QueryServiceParent(SID_STopLevelBrowser, IID_PPV_ARG(IShellBrowser, &psbTop))))
  3098. {
  3099. HWND hwndTop;
  3100. psbTop->GetWindow(&hwndTop);
  3101. psbTop->Release();
  3102. if (psbTop != this)
  3103. return SendMessage(hwndTop, WM_NOTIFY, 0, (LPARAM)pnm);
  3104. }
  3105. break;
  3106. }
  3107. default:
  3108. return CBASEBROWSER::OnNotify(pnm);
  3109. }
  3110. return S_OK;
  3111. }
  3112. // IServiceProvider stuff
  3113. //
  3114. HRESULT CWebBrowserSB::_QueryServiceParent(REFGUID guidService, REFIID riid, void **ppvObj)
  3115. {
  3116. HRESULT hres = E_FAIL;
  3117. *ppvObj = NULL;
  3118. // Pass it on to our parent
  3119. if (_psvo && _psvo->_pcli)
  3120. {
  3121. hres = IUnknown_QueryService(_psvo->_pcli, guidService, riid, ppvObj);
  3122. }
  3123. else
  3124. {
  3125. CVOCBMSG(TEXT("QueryService doesn't have _pipsite!"));
  3126. }
  3127. return hres;
  3128. }
  3129. // NOTES:
  3130. // If SID_STopLevelBrowser, go to parent (upto the top level browser)
  3131. // If SID_SWebBrowserApp, go to parent (up to the top level browser automation)
  3132. // If SID_SContainerDispatch, expose CWebBrowserOC (instead of _pauto)
  3133. // Then, try CBASEBROWSER::QueryService, which will handle SID_SHlinkFrame,
  3134. // SID_SUrlHistory, SID_SShellBrowser, etc.
  3135. // If all fails and not SID_SShellBrowser, then we go up the parent chain.
  3136. //
  3137. HRESULT CWebBrowserSB::QueryService(REFGUID guidService, REFIID riid, void **ppvObj)
  3138. {
  3139. HRESULT hr = E_FAIL; // service object not found
  3140. *ppvObj = NULL; // assume error
  3141. // if the guidService is SID_QIClientSite then delegate the iid to the
  3142. // container through a queryinterface call.
  3143. if (_psvo && _psvo->_pcli && IsEqualGUID( guidService, SID_QIClientSite))
  3144. {
  3145. return _psvo->_pcli->QueryInterface( riid, ppvObj);
  3146. }
  3147. // If guidService is SID_STopLevelBrowser, we should not ask the super
  3148. // class to handle. Instead, we ask the parent to handle (if any).
  3149. if (IsEqualGUID(guidService, SID_STopLevelBrowser) ||
  3150. IsEqualGUID(guidService, SID_STopWindow))
  3151. {
  3152. // APPCOMPAT: WebBrowser is not supposed to respond to QS(SID_SInetExp) because
  3153. // it does not support IWebBrowserApp. However, rejecting this causes
  3154. // a stack fault when opening a frame-set. We need to find out what is causing
  3155. // this stack fault but I'll backup this delta for now to stop GPF.
  3156. //
  3157. // || IsEqualGUID(guidService, SID_SWebBrowserApp)
  3158. goto AskParent;
  3159. }
  3160. if (IsEqualGUID(guidService, SID_STopFrameBrowser))
  3161. {
  3162. BOOL fAskParent = TRUE;
  3163. // Don't ask the parent if we are a desktop component and we are
  3164. // not doing drag/drop. Treat it as a top level frame. For all other
  3165. // cases, ask the parent.
  3166. if (!IsEqualIID(riid, IID_IDropTarget) && _ptfrm)
  3167. {
  3168. IUnknown *pUnkParent;
  3169. if (SUCCEEDED(_ptfrm->GetParentFrame(&pUnkParent)))
  3170. {
  3171. if (pUnkParent)
  3172. {
  3173. // Has a parent, not a desktop component
  3174. pUnkParent->Release();
  3175. }
  3176. else
  3177. {
  3178. // Doesn't have a parent, must be a desktop component so
  3179. // fall through to call our CBASEBROWSER::QueryService
  3180. fAskParent = FALSE;
  3181. }
  3182. }
  3183. }
  3184. if (fAskParent)
  3185. goto AskParent;
  3186. }
  3187. // If the containee is asking for SID_SContainerDispatch (parent),
  3188. // we should return the automation interface of the buddy CWebBrowserOC.
  3189. if (IsEqualGUID(guidService, SID_SContainerDispatch))
  3190. {
  3191. if (_psvo)
  3192. {
  3193. return _psvo->QueryInterface(riid, ppvObj);
  3194. }
  3195. return E_UNEXPECTED;
  3196. }
  3197. // If the guidService is SID_SVersionHost,
  3198. // give the host a crack at it first
  3199. //
  3200. if (IsEqualGUID(guidService, SID_SVersionHost))
  3201. {
  3202. hr = _QueryServiceParent(guidService, riid, ppvObj);
  3203. // Return if the host handled the service,
  3204. //
  3205. if (S_OK == hr)
  3206. return hr;
  3207. }
  3208. hr = CBASEBROWSER::QueryService(guidService, riid, ppvObj);
  3209. // Notes: If guidService is SID_SShellBrowser, it indicates that
  3210. // the caller wants to talk to the immediate IShellBrowser.
  3211. // We should not try our parent in that case. Doing it so will
  3212. // break nested browser (frame set). In addition, notice that
  3213. // we don't want to go up the parent chain if hr is E_NOINTERFACE
  3214. // (which indicates unsuccessfull QueryInterface).
  3215. //
  3216. // We don't want a shell view in a frame-set add buttons on the
  3217. // toolbar. We should skip AskParent if guidService is SID_SExplroerToolbar.
  3218. if (FAILED(hr) && hr != E_NOINTERFACE
  3219. && !IsEqualIID(guidService, SID_SShellBrowser)
  3220. && !IsEqualIID(guidService, SID_SExplorerToolbar))
  3221. {
  3222. AskParent:
  3223. hr = _QueryServiceParent(guidService, riid, ppvObj);
  3224. // hey, we're the top-level browser if there ain't no top-level browser
  3225. // above us. (Such as our OC embedded in AOL/CIS/VB.) We must do this
  3226. // or we don't get a _tlGlobal on the top frame, so navigation history
  3227. // is screwy and the back/forward buttons are incorrect.
  3228. if (FAILED(hr) &&
  3229. (IsEqualGUID(guidService, SID_STopLevelBrowser) ||
  3230. IsEqualGUID(guidService, SID_STopFrameBrowser) ||
  3231. IsEqualGUID(guidService, SID_STopWindow)))
  3232. {
  3233. hr = CBASEBROWSER::QueryService(guidService, riid, ppvObj);
  3234. }
  3235. }
  3236. return hr;
  3237. }
  3238. // IOleCommandTarget
  3239. //
  3240. // We simply forward to the container above our parent OC
  3241. HRESULT CWebBrowserSB::QueryStatus(const GUID *pguidCmdGroup, ULONG cCmds, OLECMD rgCmds[], OLECMDTEXT *pcmdtext)
  3242. {
  3243. HRESULT hres = OLECMDERR_E_UNKNOWNGROUP;
  3244. HRESULT hresLocal;
  3245. if (pguidCmdGroup && IsEqualGUID(*pguidCmdGroup, CGID_ShellDocView))
  3246. {
  3247. hres = S_OK;
  3248. for (ULONG i=0 ; i < cCmds ; i++)
  3249. {
  3250. if (rgCmds[i].cmdID == SHDVID_CANGOBACK ||
  3251. rgCmds[i].cmdID == SHDVID_CANGOFORWARD)
  3252. {
  3253. hresLocal = CBASEBROWSER::QueryStatus(pguidCmdGroup, 1, &rgCmds[i], pcmdtext);
  3254. }
  3255. else if (_psvo && _psvo->_pctContainer)
  3256. {
  3257. hresLocal = _psvo->_pctContainer->QueryStatus(pguidCmdGroup, 1, &rgCmds[i], pcmdtext);
  3258. if (hresLocal == OLECMDERR_E_UNKNOWNGROUP || hresLocal == OLECMDERR_E_NOTSUPPORTED)
  3259. {
  3260. hresLocal = CBASEBROWSER::QueryStatus(pguidCmdGroup, cCmds, rgCmds, pcmdtext);
  3261. }
  3262. }
  3263. else
  3264. hresLocal = OLECMDERR_E_NOTSUPPORTED;
  3265. if (hresLocal != S_OK) hres = hresLocal;
  3266. }
  3267. }
  3268. else
  3269. {
  3270. if (_psvo && _psvo->_pctContainer)
  3271. hres = _psvo->_pctContainer->QueryStatus(pguidCmdGroup, cCmds, rgCmds, pcmdtext);
  3272. // if container does not support the command try base browser
  3273. // before we only used to return an error
  3274. if (hres == OLECMDERR_E_UNKNOWNGROUP || hres == OLECMDERR_E_NOTSUPPORTED)
  3275. {
  3276. hres = CBASEBROWSER::QueryStatus(pguidCmdGroup, cCmds, rgCmds, pcmdtext);
  3277. }
  3278. }
  3279. return hres;
  3280. }
  3281. struct WBCMDLIST {
  3282. const GUID* pguidCmdGroup;
  3283. DWORD nCmdID;
  3284. };
  3285. //
  3286. // SBCMDID_CANCELNAVIGATION:
  3287. // Don't pass SBCMDID_CANCELNAVIGATION up to ROOT browser. Canceling
  3288. // here doesn't need to be forwarded and will cause navigations of to
  3289. // initiated by javascript: navigations in this frame to be aborted.
  3290. //
  3291. // SHDVID_ACTIVATEMENOW:
  3292. // The DocHost's request to activate the pending view must be handled
  3293. // by THIS browser, not the parent's -- if we're in a frameset page,
  3294. // we've probably already activated the top-level browser, now we may
  3295. // be trying to activate an individual frame.
  3296. //
  3297. const WBCMDLIST c_acmdWBSB[] = {
  3298. { NULL, OLECMDID_HTTPEQUIV },
  3299. { NULL, OLECMDID_HTTPEQUIV_DONE },
  3300. { &CGID_ShellDocView, SHDVID_GETPENDINGOBJECT },
  3301. { &CGID_ShellDocView, SHDVID_ACTIVATEMENOW },
  3302. { &CGID_ShellDocView, SHDVID_DOCFAMILYCHARSET },
  3303. { &CGID_Explorer, SBCMDID_CANCELNAVIGATION },
  3304. { &CGID_Explorer, SBCMDID_CREATESHORTCUT },
  3305. { &CGID_ShellDocView, SHDVID_CHECKINCACHEIFOFFLINE },
  3306. { &CGID_ShellDocView, SHDVID_SETPRINTSTATUS },
  3307. { &CGID_ShellDocView, SHDVID_FIREFILEDOWNLOAD },
  3308. { &CGID_DocHostCmdPriv, DOCHOST_DOCCANNAVIGATE },
  3309. { &CGID_InternetExplorer, IECMDID_BEFORENAVIGATE_GETSHELLBROWSE },
  3310. { &CGID_InternetExplorer, IECMDID_BEFORENAVIGATE_DOEXTERNALBROWSE },
  3311. { &CGID_InternetExplorer, IECMDID_BEFORENAVIGATE_GETIDLIST },
  3312. { &CGID_DocHostCmdPriv, DOCHOST_SETBROWSERINDEX },
  3313. };
  3314. HRESULT CWebBrowserSB::Exec(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANTARG *pvarargIn, VARIANTARG *pvarargOut)
  3315. {
  3316. HRESULT hres = OLECMDERR_E_UNKNOWNGROUP;
  3317. //
  3318. // First, test if the spcified command is supposed to processed by
  3319. // this browser or not. If that's the case, just call CBASEBROWSER::Exec
  3320. // and return.
  3321. //
  3322. for (int i=0; i<ARRAYSIZE(c_acmdWBSB); i++)
  3323. {
  3324. if (nCmdID == c_acmdWBSB[i].nCmdID)
  3325. {
  3326. if (pguidCmdGroup==NULL || c_acmdWBSB[i].pguidCmdGroup==NULL)
  3327. {
  3328. if (pguidCmdGroup==c_acmdWBSB[i].pguidCmdGroup)
  3329. {
  3330. return CBASEBROWSER::Exec(pguidCmdGroup, nCmdID, nCmdexecopt, pvarargIn, pvarargOut);
  3331. }
  3332. }
  3333. else if (IsEqualGUID(*pguidCmdGroup, *c_acmdWBSB[i].pguidCmdGroup))
  3334. {
  3335. return CBASEBROWSER::Exec(pguidCmdGroup, nCmdID, nCmdexecopt, pvarargIn, pvarargOut);
  3336. }
  3337. }
  3338. }
  3339. // In some cases, we need perform some additional operations
  3340. // before passing it to the parent.
  3341. //
  3342. if (pguidCmdGroup == NULL)
  3343. {
  3344. switch(nCmdID) {
  3345. case OLECMDID_SETDOWNLOADSTATE:
  3346. if (pvarargIn)
  3347. {
  3348. _setDescendentNavigate(pvarargIn);
  3349. }
  3350. break;
  3351. }
  3352. }
  3353. else if (IsEqualGUID(*pguidCmdGroup, CGID_ShellDocView))
  3354. {
  3355. switch (nCmdID)
  3356. {
  3357. /* The DocHost's request to activate the pending view must be handled
  3358. * by THIS browser, not the parent's -- then we forward up the chain
  3359. * so that all potentially blocked frames can attempt to deactivate
  3360. */
  3361. case SHDVID_DEACTIVATEMENOW:
  3362. if (_cbScriptNesting > 0)
  3363. _cbScriptNesting--;
  3364. hres = CBASEBROWSER::Exec(pguidCmdGroup, nCmdID, nCmdexecopt, pvarargIn, pvarargOut);
  3365. if (FAILED(hres) || _cbScriptNesting > 0)
  3366. return hres;
  3367. break;
  3368. case SHDVID_NODEACTIVATENOW:
  3369. _cbScriptNesting++;
  3370. if (_cbScriptNesting > 1)
  3371. return S_OK;
  3372. break;
  3373. case SHDVID_DELEGATEWINDOWOM:
  3374. if (_psvo && _psvo->_pauto)
  3375. {
  3376. // Forward this command to the CIEFrameAuto instance for this webOC.
  3377. return IUnknown_Exec(_psvo->_pauto, &CGID_ShellDocView, nCmdID, 0, pvarargIn, NULL);
  3378. }
  3379. break;
  3380. }
  3381. }
  3382. else if (IsEqualGUID(*pguidCmdGroup, CGID_Explorer))
  3383. {
  3384. // this needs to be handled by the specific browser that
  3385. // received the exec.
  3386. switch (nCmdID)
  3387. {
  3388. case SBCMDID_UPDATETRAVELLOG:
  3389. case SBCMDID_REPLACELOCATION:
  3390. return CBASEBROWSER::Exec(pguidCmdGroup, nCmdID, nCmdexecopt, pvarargIn, pvarargOut);
  3391. case SBCMDID_SETSECURELOCKICON:
  3392. {
  3393. CBASEBROWSER::Exec(pguidCmdGroup, nCmdID, nCmdexecopt, pvarargIn, pvarargOut);
  3394. // Let the WebBrowserOC fire the event
  3395. if (_psvo)
  3396. {
  3397. _psvo->_OnSetSecureLockIcon(_bbd._eSecureLockIcon);
  3398. }
  3399. }
  3400. return S_OK;
  3401. }
  3402. }
  3403. else if (IsEqualGUID(CGID_ExplorerBarDoc, *pguidCmdGroup))
  3404. {
  3405. // These are ignored so that Explorer bar changes are done once - and only in response to
  3406. // global changes applied to top Document if frameset of browser.
  3407. // NOT for changes applied to frames
  3408. // NOT for changes applied to browserbands
  3409. return S_OK;
  3410. }
  3411. //
  3412. // Forward this EXEC to the container (if we have).
  3413. //
  3414. if (_psvo && _psvo->_pctContainer)
  3415. hres = _psvo->_pctContainer->Exec(pguidCmdGroup, nCmdID, nCmdexecopt, pvarargIn, pvarargOut);
  3416. //
  3417. // if the above exec failed, we're probably in some random container
  3418. // so let CBASEBROWSER try to simulate a top-level frame.
  3419. // might as well be a bit paranoid and make sure it failed with "i dunno"
  3420. //
  3421. if (hres == OLECMDERR_E_UNKNOWNGROUP || hres == OLECMDERR_E_NOTSUPPORTED)
  3422. {
  3423. if (pguidCmdGroup==NULL && nCmdID==OLECMDID_SETDOWNLOADSTATE && _psvo)
  3424. {
  3425. TraceMsg(DM_FORSEARCHBAND, "WBSB::QueryStatus Container does not support OLECMDID_SETDOWNLOADSTATE");
  3426. hres = _psvo->_SetDownloadState(hres, nCmdexecopt, pvarargIn);
  3427. }
  3428. if (hres != S_OK)
  3429. {
  3430. hres = CBASEBROWSER::Exec(pguidCmdGroup, nCmdID, nCmdexecopt, pvarargIn, pvarargOut);
  3431. }
  3432. }
  3433. return hres;
  3434. }
  3435. HRESULT CWebBrowserSB::_SwitchActivationNow()
  3436. {
  3437. CBASEBROWSER::_SwitchActivationNow();
  3438. if (_bbd._psv &&
  3439. _psvo &&
  3440. _psvo->_nActivate < OC_INPLACEACTIVE &&
  3441. _psvo->_dwDrawAspect)
  3442. {
  3443. // pass on the SetExtent to the now ready browser...
  3444. IPrivateOleObject * pPrivOle;
  3445. if (SUCCEEDED(_bbd._psv->QueryInterface(IID_PPV_ARG(IPrivateOleObject, &pPrivOle))))
  3446. {
  3447. // we have an ole object, delegate downwards...
  3448. pPrivOle->SetExtent( _psvo->_dwDrawAspect, &_psvo->_sizeHIM );
  3449. pPrivOle->Release();
  3450. }
  3451. }
  3452. return S_OK;
  3453. }
  3454. BOOL CWebBrowserSB::_HeyMoe_IsWiseGuy()
  3455. {
  3456. BOOL fRet;
  3457. if (_psvo)
  3458. {
  3459. fRet = _psvo->_HeyMoe_IsWiseGuy();
  3460. }
  3461. else
  3462. {
  3463. fRet = FALSE;
  3464. }
  3465. return fRet;
  3466. }
  3467. HRESULT CWebBrowserSB::BrowseObject(LPCITEMIDLIST pidl, UINT wFlags)
  3468. {
  3469. // if client does not specify we will do so for them
  3470. if (SBSP_DEFBROWSER == (wFlags & (SBSP_NEWBROWSER | SBSP_SAMEBROWSER)))
  3471. {
  3472. IShellBrowser *psbDesktop;
  3473. if (SUCCEEDED(QueryService(SID_SShellDesktop, IID_PPV_ARG(IShellBrowser, &psbDesktop))))
  3474. {
  3475. HRESULT hr = psbDesktop->BrowseObject(pidl, wFlags);
  3476. psbDesktop->Release();
  3477. return hr;
  3478. }
  3479. wFlags |= SBSP_SAMEBROWSER; // always navigate in place
  3480. }
  3481. return CBASEBROWSER::BrowseObject(pidl, wFlags);
  3482. }