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

3941 lines
125 KiB

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