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.

1644 lines
49 KiB

  1. #include "shellprv.h"
  2. #include <shellp.h>
  3. #include "ole2dup.h"
  4. #include "defview.h"
  5. #include "bookmk.h"
  6. #include <sfview.h>
  7. #include "defviewp.h"
  8. #include "ids.h"
  9. #include <htiface.h>
  10. #include <olectl.h>
  11. #include "mshtml.h"
  12. #include <mshtmdid.h>
  13. #include <shguidp.h> // get the CLSID definitions, the bits are built into shguidp.lib
  14. #include "basefvcb.h"
  15. #include "clsobj.h"
  16. #define TF_FOCUS TF_ALLOC
  17. CSFVFrame::~CSFVFrame()
  18. {
  19. ATOMICRELEASE(_pvoActive);
  20. ATOMICRELEASE(_pActive);
  21. ATOMICRELEASE(_pDocView);
  22. ATOMICRELEASE(_pOleObj);
  23. if (_dwConnectionCookie)
  24. _RemoveReadyStateNotifyCapability();
  25. ATOMICRELEASE(_pOleObjNew);
  26. }
  27. // Default implementation of SFVM_GETVIEWDATA is to grab the info
  28. // from SFVM_GETVIEWS. We no longer provide a default implementation
  29. // of that message, so if SFVM_GETVIEWS fails, we manually look in:
  30. // shellex\ExtShellFolderViews\{VID_WebView}\PersistMoniker
  31. //
  32. HRESULT CCallback::OnGetWebViewTemplate(DWORD pv, UINT uViewMode, SFVM_WEBVIEW_TEMPLATE_DATA* pvit)
  33. {
  34. CDefView* pView = IToClass(CDefView, _cCallback, this);
  35. // try the old message
  36. pvit->szWebView[0] = 0;
  37. // For now, use the old one - clean up soon...
  38. SFVM_VIEWINFO_DATA data;
  39. data.bWantWebview = TRUE;
  40. HRESULT hr = pView->CallCB(SFVM_GETVIEWINFO, (WPARAM)uViewMode, (LPARAM)&data);
  41. if (SUCCEEDED(hr))
  42. {
  43. hr = StringCchCopy(pvit->szWebView, ARRAYSIZE(pvit->szWebView), data.szWebView);
  44. }
  45. else
  46. {
  47. if (FAILED(hr))
  48. hr = TryLegacyGetViews(pvit);
  49. }
  50. return hr;
  51. }
  52. void CleanUpDocView(IOleDocumentView* pDocView, IOleObject* pOleObj)
  53. {
  54. pDocView->UIActivate(FALSE);
  55. IOleInPlaceObject* pipo;
  56. if (SUCCEEDED(pOleObj->QueryInterface(IID_PPV_ARG(IOleInPlaceObject, &pipo))))
  57. {
  58. pipo->InPlaceDeactivate();
  59. pipo->Release();
  60. }
  61. pDocView->CloseView(0);
  62. pDocView->SetInPlaceSite(NULL);
  63. pDocView->Release();
  64. }
  65. void CSFVFrame::_CleanupOldDocObject( )
  66. {
  67. //See if we have already switched to the new Ole Obj
  68. if (_pDocView)
  69. {
  70. //Save the current values first!
  71. IOleObject *pOleObjOld = _pOleObj;
  72. IOleDocumentView *pDocViewOld = _pDocView;
  73. _pDocView = NULL;
  74. _pOleObj = NULL;
  75. CleanUpDocView(pDocViewOld, pOleObjOld);
  76. _CleanUpOleObjAndDt(pOleObjOld);
  77. SetActiveObject(NULL, NULL);
  78. }
  79. if (_dwConnectionCookie)
  80. _RemoveReadyStateNotifyCapability();
  81. _CleanupNewOleObj();
  82. }
  83. void CSFVFrame::_CleanUpOleObj(IOleObject* pOleObj)
  84. {
  85. pOleObj->Close(OLECLOSE_NOSAVE);
  86. pOleObj->SetClientSite(NULL);
  87. pOleObj->Release();
  88. }
  89. void CSFVFrame::_CleanUpOleObjAndDt(IOleObject* pOleObj)
  90. {
  91. _CleanUpOleObj(pOleObj);
  92. // If we have a wrapping droptarget, release it now.
  93. IDropTarget* pdtTemp = _cSite._dt._pdtFrame;
  94. if (pdtTemp)
  95. {
  96. _cSite._dt._pdtFrame = NULL;
  97. pdtTemp->Release();
  98. }
  99. }
  100. void CSFVFrame::_CleanupNewOleObj()
  101. {
  102. IOleObject *pOleObj = _pOleObjNew;
  103. if (pOleObj)
  104. {
  105. _pOleObjNew = NULL;
  106. _CleanUpOleObj(pOleObj);
  107. }
  108. }
  109. void DisableActiveDesktop()
  110. {
  111. SHELLSTATE ss;
  112. // Disable this settings in the registry!
  113. ss.fDesktopHTML = FALSE;
  114. SHGetSetSettings(&ss, SSF_DESKTOPHTML, TRUE); // Write back the new
  115. // Tell the user that we have just disabled the active desktop!
  116. ShellMessageBox(HINST_THISDLL, NULL, MAKEINTRESOURCE(IDS_HTMLFILE_NOTFOUND),
  117. MAKEINTRESOURCE(IDS_DESKTOP),
  118. MB_OK | MB_ICONEXCLAMATION | MB_SETFOREGROUND);
  119. }
  120. HRESULT CSFVFrame::_GetCurrentZone(IOleObject *pOleObj, VARIANT *pvar)
  121. {
  122. HRESULT hr = S_OK;
  123. CDefView* pView = IToClass(CDefView, _cFrame, this);
  124. VariantInit(pvar);
  125. V_VT(pvar) = VT_EMPTY;
  126. IOleCommandTarget* pct;
  127. if (pOleObj && SUCCEEDED(GetCommandTarget(&pct)))
  128. {
  129. hr = pct->Exec(&CGID_Explorer, SBCMDID_MIXEDZONE, 0, 0, pvar);
  130. pct->Release();
  131. }
  132. else
  133. {
  134. V_VT(pvar) = VT_UI4;
  135. V_UI4(pvar) = URLZONE_LOCAL_MACHINE; // Default is "My Computer"
  136. pView->CallCB(SFVM_GETZONE, 0, (LPARAM)&V_UI4(pvar));
  137. }
  138. if (V_VT(pvar) == VT_UI4) // We were able to figure out what zone we are in
  139. { } // the zone is just fine
  140. else if (V_VT(pvar) == VT_NULL) // MSHTML has figured us to be in a mixed zone
  141. V_UI4(pvar) = ZONE_MIXED;
  142. else // We don't have zone info
  143. V_UI4(pvar) = ZONE_UNKNOWN;
  144. V_VT(pvar) = VT_UI4;
  145. return hr;
  146. }
  147. HRESULT CSFVFrame::_UpdateZonesStatusPane(IOleObject *pOleObj)
  148. {
  149. CDefView* pView = IToClass(CDefView, _cFrame, this);
  150. VARIANT var;
  151. HRESULT hr = _GetCurrentZone(pOleObj, &var);
  152. // Tell CShellbrowser to show the zone stuff in the second pane
  153. ASSERT(V_VT(&var) == VT_UI4);
  154. // The "2" means "second pane"
  155. V_UI4(&var) = MAKELONG(2, V_UI4(&var));
  156. IUnknown_Exec(pView->_psb, &CGID_Explorer, SBCMDID_MIXEDZONE, 0, &var, NULL);
  157. ASSERT((V_VT(&var) == VT_I4) || (V_VT(&var) == VT_UI4) ||
  158. (V_VT(&var) == VT_EMPTY) || (V_VT(&var) == VT_NULL));
  159. return hr;
  160. }
  161. HRESULT CSFVFrame::_GetHTMLBackgroundColor(COLORREF *pclr)
  162. {
  163. HRESULT hr = E_FAIL;
  164. if (_bgColor == CLR_INVALID)
  165. hr = IUnknown_HTMLBackgroundColor(_pOleObj, &_bgColor);
  166. else
  167. hr = S_OK; // cached
  168. if (SUCCEEDED(hr))
  169. *pclr = _bgColor;
  170. return hr;
  171. }
  172. #ifdef DEBUG
  173. BOOL_PTR CALLBACK s_WVDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM
  174. lParam)
  175. {
  176. switch (uMsg)
  177. {
  178. case WM_INITDIALOG:
  179. {
  180. RECT rc;
  181. if (GetWindowRect(hWnd, &rc))
  182. {
  183. HWND hEdit = CreateWindow(TEXT("edit"), NULL, WS_CHILD|WS_VISIBLE|ES_MULTILINE|ES_AUTOVSCROLL, 10, 10, (rc.right-rc.left)-20, (rc.bottom-rc.top)-20, hWnd, NULL, NULL, 0);
  184. if (hEdit)
  185. {
  186. SetWindowTextA(hEdit, (LPCSTR)lParam);
  187. }
  188. }
  189. SetWindowText(hWnd, TEXT("WebView Content (DEBUG)"));
  190. break;
  191. }
  192. case WM_COMMAND:
  193. switch (GET_WM_COMMAND_ID(wParam, lParam))
  194. {
  195. case IDCANCEL:
  196. EndDialog(hWnd, 0);
  197. break;
  198. }
  199. break;
  200. }
  201. return FALSE;
  202. }
  203. void CSFVFrame::_ShowWebViewContent()
  204. {
  205. CDefView* pView = IToClass(CDefView, _cCallback, this);
  206. HRESULT hr = E_FAIL;
  207. LPSTR pszFree = NULL;
  208. if (_pOleObj)
  209. {
  210. IStream* pstm = SHCreateMemStream(NULL, 0);
  211. if (pstm)
  212. {
  213. VARIANTARG vt;
  214. vt.vt = VT_UNKNOWN;
  215. vt.punkVal = pstm;
  216. #define IDM_DEBUG_GETTREETEXT 7102 // stolen from mshtml\src\include\privcid.h
  217. if (SUCCEEDED(IUnknown_Exec(_pOleObj, &CGID_MSHTML, IDM_DEBUG_GETTREETEXT, 0, &vt, NULL)))
  218. {
  219. STATSTG stg;
  220. if (SUCCEEDED(pstm->Stat(&stg, 0)))
  221. {
  222. pszFree = (LPSTR)LocalAlloc(LPTR, stg.cbSize.LowPart+2); // stream doesn't include NULL...
  223. if (pszFree)
  224. {
  225. pstm->Seek(g_li0, STREAM_SEEK_SET, NULL);
  226. pstm->Read(pszFree, stg.cbSize.LowPart, NULL);
  227. }
  228. }
  229. }
  230. pstm->Release();
  231. }
  232. }
  233. // I'm not sure if the output from Trident is always ANSI, but right now that seems to be the case.
  234. LPSTR pszMessage = pszFree ? pszFree : "Error collecting WebView content";
  235. DialogBoxParam(HINST_THISDLL, MAKEINTRESOURCE(DLG_DRV_HWTAB), pView->_hwndView, s_WVDlgProc, (LPARAM)pszFree);
  236. if (pszFree)
  237. LocalFree(pszFree);
  238. }
  239. #endif
  240. // ready state complete has occured, ready to do the switch thing.
  241. HRESULT CSFVFrame::_SwitchToNewOleObj()
  242. {
  243. HRESULT hr = S_OK;
  244. if (!_fSwitchedToNewOleObj && _pOleObjNew)
  245. {
  246. _fSwitchedToNewOleObj = TRUE;
  247. CDefView* pView = IToClass(CDefView, _cFrame, this);
  248. //Save the current values first!
  249. IOleObject *pOleObjOld = _pOleObj;
  250. IOleDocumentView *pDocViewOld = _pDocView;
  251. IOleObject *pOleObjNew = _pOleObjNew;
  252. _pDocView = NULL;
  253. _pOleObj = NULL;
  254. _pOleObjNew = NULL;
  255. //If we already have one, destroy it!
  256. if (pDocViewOld)
  257. {
  258. //To prevent flashing, set the flag that avoids the painting
  259. SendMessage(pView->_hwndView, WM_SETREDRAW, 0, 0);
  260. CleanUpDocView(pDocViewOld, pOleObjOld);
  261. _CleanUpOleObjAndDt(pOleObjOld);
  262. SetActiveObject(NULL, NULL);
  263. //Is the ViewWindow still around?
  264. if (IsWindow(pView->_hwndView))
  265. {
  266. SendMessage(pView->_hwndView, WM_SETREDRAW, TRUE, 0);
  267. if (pView->_hwndListview)
  268. InvalidateRect(pView->_hwndListview, NULL, TRUE);
  269. }
  270. }
  271. // HACK: We need to set the host names for Word to force embedding mode
  272. pOleObjNew->SetHostNames(L"1", L"2");
  273. OleRun(pOleObjNew);
  274. IOleDocumentView* pDocView = NULL;
  275. IOleDocument* pDocObj;
  276. hr = pOleObjNew->QueryInterface(IID_PPV_ARG(IOleDocument, &pDocObj));
  277. if (SUCCEEDED(hr))
  278. {
  279. hr = pDocObj->CreateView(&_cSite, NULL, 0, &pDocView);
  280. if (SUCCEEDED(hr))
  281. {
  282. RECT rcView;
  283. pDocView->SetInPlaceSite(&_cSite);
  284. GetClientRect(pView->_hwndView, &rcView);
  285. hr = pOleObjNew->DoVerb(OLEIVERB_INPLACEACTIVATE, NULL,
  286. &_cSite, (UINT)-1, pView->_hwndView, &rcView);
  287. if (FAILED(hr))
  288. CleanUpDocView(pDocView, pOleObjNew);
  289. }
  290. pDocObj->Release();
  291. }
  292. if (SUCCEEDED(hr))
  293. {
  294. hr = S_OK; // S_FALSE -> S_OK, needed?
  295. ASSERT(_pOleObj == NULL);
  296. ASSERT(_pDocView == NULL);
  297. _pDocView = pDocView;
  298. pDocView->AddRef(); // copy hold the ref for our copy
  299. _pOleObj = pOleObjNew;
  300. _pOleObjNew = NULL;
  301. RECT rcClient;
  302. // Make sure the new view is the correct size
  303. GetClientRect(pView->_hwndView, &rcClient);
  304. SetRect(&rcClient);
  305. // If this is desktop, then we need to see the listview's background color
  306. if (pView->_IsDesktop())
  307. {
  308. _bgColor = CLR_INVALID;
  309. pView->_SetFolderColors(); //Tell the listview about color change!
  310. }
  311. }
  312. else
  313. {
  314. if (pView->_IsDesktop())
  315. PostMessage(pView->_hwndView, WM_DSV_DISABLEACTIVEDESKTOP, 0, 0);
  316. // Clean up if necessary
  317. _CleanupNewOleObj();
  318. }
  319. ATOMICRELEASE(pDocView);
  320. }
  321. return hr;
  322. }
  323. // IBindStatusCallback impl
  324. HRESULT CSFVFrame::CBindStatusCallback::QueryInterface(REFIID riid, void **ppv)
  325. {
  326. static const QITAB qit[] = {
  327. QITABENT(CSFVFrame::CBindStatusCallback, IBindStatusCallback), // IID_IBindStatusCallback
  328. QITABENT(CSFVFrame::CBindStatusCallback, IServiceProvider), // IID_IServiceProvider
  329. { 0 }
  330. };
  331. return QISearch(this, qit, riid, ppv);
  332. }
  333. ULONG CSFVFrame::CBindStatusCallback::AddRef(void)
  334. {
  335. CSFVFrame* pFrame = IToClass(CSFVFrame, _bsc, this);
  336. return pFrame->AddRef();
  337. }
  338. ULONG CSFVFrame::CBindStatusCallback::Release(void)
  339. {
  340. CSFVFrame* pFrame = IToClass(CSFVFrame, _bsc, this);
  341. return pFrame->Release();
  342. }
  343. HRESULT CSFVFrame::CBindStatusCallback::OnStartBinding(DWORD grfBSCOption, IBinding *pib)
  344. {
  345. return S_OK;
  346. }
  347. HRESULT CSFVFrame::CBindStatusCallback::GetPriority(LONG *pnPriority)
  348. {
  349. *pnPriority = NORMAL_PRIORITY_CLASS;
  350. return S_OK;
  351. }
  352. HRESULT CSFVFrame::CBindStatusCallback::OnLowResource(DWORD reserved)
  353. {
  354. return S_OK;
  355. }
  356. HRESULT CSFVFrame::CBindStatusCallback::OnProgress(ULONG ulProgress, ULONG ulProgressMax, ULONG ulStatusCode, LPCWSTR szStatusText)
  357. {
  358. return S_OK;
  359. }
  360. HRESULT CSFVFrame::CBindStatusCallback::OnStopBinding(HRESULT hr, LPCWSTR pszError)
  361. {
  362. return S_OK;
  363. }
  364. HRESULT CSFVFrame::CBindStatusCallback::GetBindInfo(DWORD *grfBINDINFOF, BINDINFO *pbindinfo)
  365. {
  366. return S_OK;
  367. }
  368. HRESULT CSFVFrame::CBindStatusCallback::OnDataAvailable(DWORD grfBSCF, DWORD dwSize, FORMATETC *pformatetc, STGMEDIUM *pstgmed)
  369. {
  370. return S_OK;
  371. }
  372. HRESULT CSFVFrame::CBindStatusCallback::OnObjectAvailable(REFIID riid, IUnknown *punk)
  373. {
  374. return S_OK;
  375. }
  376. HRESULT CSFVFrame::CBindStatusCallback::QueryService(REFGUID guidService, REFIID riid, void **ppv)
  377. {
  378. CSFVFrame* pFrame = IToClass(CSFVFrame, _bsc, this);
  379. if (IsEqualGUID(guidService, SID_DefView))
  380. {
  381. // QueryService from a pluggable protocol/mime filter winds up
  382. // here during the Bind, but Trident re-binds during F5 processing
  383. // so the QueryService winds up directly at _cSite. Handle all
  384. // SID_DefView processing there so there's no discrepencies.
  385. //
  386. return pFrame->_cSite.QueryService(guidService, riid, ppv);
  387. }
  388. *ppv = NULL;
  389. return E_FAIL;
  390. }
  391. HRESULT CSFVFrame::_CreateNewOleObjFromMoniker(LPCWSTR wszMoniker, IOleObject **ppOleObj)
  392. {
  393. CDefView* pView = IToClass(CDefView, _cFrame, this);
  394. HRESULT hr = E_FAIL;
  395. IOleObject* pOleObj = NULL;
  396. if (wszMoniker[0])
  397. {
  398. LPWSTR pwszExtension = PathFindExtensionW(wszMoniker);
  399. // Only htt's are allowed
  400. if (StrCmpIW(pwszExtension, L".htt") == 0)
  401. {
  402. IMoniker * pMoniker;
  403. hr = CreateURLMoniker(NULL, wszMoniker, &pMoniker);
  404. if (SUCCEEDED(hr))
  405. {
  406. IBindCtx * pbc;
  407. hr = CreateBindCtx(0, &pbc);
  408. if (SUCCEEDED(hr))
  409. {
  410. // NOTE: We only support synchronous bind here!
  411. //
  412. //
  413. // Associate the client site as an object parameter to this
  414. // bind context so that Trident can pick it up while processing
  415. // IPersistMoniker::Load().
  416. //
  417. pbc->RegisterObjectParam(WSZGUID_OPID_DocObjClientSite,
  418. SAFECAST((&_cSite), IOleClientSite*));
  419. RegisterBindStatusCallback(pbc, SAFECAST(&_bsc, IBindStatusCallback*), 0, 0);
  420. hr = pMoniker->BindToObject(pbc, NULL, IID_PPV_ARG(IOleObject, &pOleObj));
  421. if (FAILED(hr))
  422. {
  423. if (pView->_IsDesktop())
  424. PostMessage(pView->_hwndView, WM_DSV_DISABLEACTIVEDESKTOP, 0, 0);
  425. }
  426. RevokeBindStatusCallback(pbc, SAFECAST(&_bsc, IBindStatusCallback*));
  427. pbc->Release();
  428. }
  429. pMoniker->Release();
  430. }
  431. }
  432. }
  433. *ppOleObj = pOleObj;
  434. return hr;
  435. }
  436. HRESULT CSFVFrame::_GetCurrentWebViewMoniker(LPWSTR pszCurrentMoniker, DWORD cchCurrentMoniker)
  437. {
  438. HRESULT hr = StringCchCopy(pszCurrentMoniker, cchCurrentMoniker, _szCurrentWebViewMoniker);
  439. if (SUCCEEDED(hr))
  440. {
  441. if (pszCurrentMoniker[0] == TEXT('\0'))
  442. {
  443. hr = E_FAIL;
  444. }
  445. }
  446. return hr;
  447. }
  448. // Show Web View content for the specified template/moniker
  449. //
  450. HRESULT CSFVFrame::ShowWebView(LPCWSTR pszMoniker)
  451. {
  452. if (GetSystemMetrics(SM_CLEANBOOT))
  453. return E_FAIL;
  454. // kill previous readystatenotify and cleanup old pending hoster.
  455. //
  456. // TODO: move into _CleanupNewOleObj
  457. if (_dwConnectionCookie)
  458. _RemoveReadyStateNotifyCapability();
  459. // Clean up if a new Ole object is already awaiting ready state
  460. if (_pOleObjNew)
  461. _CleanupNewOleObj(); // TODO: rename to _CleanupPendingView
  462. ASSERT(_dwConnectionCookie == NULL);
  463. ASSERT(_pOleObjNew == NULL);
  464. // Create and initialize the new old object!
  465. IOleObject *pOleObj;
  466. HRESULT hr = _CreateNewOleObjFromMoniker(pszMoniker, &pOleObj);
  467. if (SUCCEEDED(hr) && pOleObj)
  468. {
  469. if (!_pOleObjNew)
  470. {
  471. CDefView* pView = IToClass(CDefView, _cFrame, this);
  472. hr = StringCchCopy(_szCurrentWebViewMoniker, ARRAYSIZE(_szCurrentWebViewMoniker), pszMoniker);
  473. if (SUCCEEDED(hr))
  474. {
  475. hr = _ShowExtView_Helper(pOleObj); // takes ownership of pOleObj (yuck)
  476. pOleObj->SetClientSite(&_cSite);
  477. pView->ShowHideListView(); // we just changed IsWebView
  478. }
  479. else
  480. {
  481. pOleObj->Release();
  482. }
  483. }
  484. else
  485. {
  486. // Yikes! We got reentered during the creation of the OleObj, blow away the object
  487. // and just return.
  488. pOleObj->Release();
  489. }
  490. }
  491. return hr;
  492. }
  493. HRESULT CSFVFrame::HideWebView()
  494. {
  495. CDefView* pView = IToClass(CDefView, _cFrame, this);
  496. _szCurrentWebViewMoniker[0] = 0;
  497. _CleanupOldDocObject();
  498. pView->ShowHideListView(); // we just changed IsWebView
  499. return S_OK;
  500. }
  501. HRESULT CSFVFrame::_ShowExtView_Helper(IOleObject* pOleObj)
  502. {
  503. HRESULT hr;
  504. // Don't leak the old object, it must be NULL at this point
  505. ASSERT(_pOleObjNew == NULL);
  506. // Save the new ole object
  507. _pOleObjNew = pOleObj;
  508. _fSwitchedToNewOleObj = FALSE;
  509. // Establish to connection point to receive the READYSTATE notification.
  510. if (!_SetupReadyStateNotifyCapability())
  511. {
  512. _SwitchToNewOleObj();
  513. _UpdateZonesStatusPane(_pOleObj);
  514. // If the object doesn't support readystate (or it's already interactive)
  515. // then we return S_OK to indicate synchronous switch.
  516. hr = S_OK;
  517. }
  518. else
  519. {
  520. // We're waiting on the docobj, we'll call _SwitchToNewOleObj
  521. // when it goes interactive...
  522. hr = S_FALSE;
  523. }
  524. return hr;
  525. }
  526. BOOL CSFVFrame::_SetupReadyStateNotifyCapability()
  527. {
  528. // By default we don't have gray-flash communication
  529. BOOL fSupportsReadystate = FALSE;
  530. // Sanity Check
  531. if (!_pOleObjNew)
  532. return fSupportsReadystate;
  533. // Check for proper readystate support
  534. BOOL fReadyStateOK = FALSE;
  535. IDispatch *pdisp;
  536. if (SUCCEEDED(_pOleObjNew->QueryInterface(IID_PPV_ARG(IDispatch, &pdisp))))
  537. {
  538. EXCEPINFO exInfo;
  539. VARIANTARG va = {0};
  540. DISPPARAMS dp = {0};
  541. if (SUCCEEDED(pdisp->Invoke(DISPID_READYSTATE, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET, &dp, &va, &exInfo, NULL)))
  542. {
  543. if ((va.vt == VT_I4) && (va.lVal < READYSTATE_COMPLETE))
  544. {
  545. fReadyStateOK = TRUE;
  546. }
  547. }
  548. pdisp->Release();
  549. }
  550. if (fReadyStateOK)
  551. {
  552. // Check and Set-Up IPropertyNotifySink
  553. if (SUCCEEDED(ConnectToConnectionPoint(SAFECAST(this, IPropertyNotifySink*), IID_IPropertyNotifySink, TRUE, _pOleObjNew, &_dwConnectionCookie, NULL)))
  554. {
  555. fSupportsReadystate = TRUE;
  556. _fReadyStateInteractiveProcessed = FALSE;
  557. _fReadyStateComplete = FALSE;
  558. _pOleObjReadyState = _pOleObjNew;
  559. _pOleObjReadyState->AddRef();
  560. }
  561. }
  562. return fSupportsReadystate;
  563. }
  564. BOOL CSFVFrame::_RemoveReadyStateNotifyCapability()
  565. {
  566. BOOL fRet = FALSE;
  567. if (_dwConnectionCookie)
  568. {
  569. ASSERT(_pOleObjReadyState);
  570. ConnectToConnectionPoint(NULL, IID_IPropertyNotifySink, FALSE, _pOleObjReadyState, &_dwConnectionCookie, NULL);
  571. ATOMICRELEASE(_pOleObjReadyState);
  572. fRet = TRUE;
  573. _dwConnectionCookie = 0;
  574. }
  575. return fRet;
  576. }
  577. HWND CSFVFrame::GetExtendedViewWindow()
  578. {
  579. HWND hwnd;
  580. if (SUCCEEDED(IUnknown_GetWindow(_pDocView, &hwnd)))
  581. return hwnd;
  582. if (_pActive && SUCCEEDED(_pActive->GetWindow(&hwnd)))
  583. return hwnd;
  584. return NULL;
  585. }
  586. STDMETHODIMP CSFVSite::QueryInterface(REFIID riid, void **ppv)
  587. {
  588. static const QITAB qit[] = {
  589. QITABENT(CSFVSite, IOleInPlaceSite),
  590. QITABENTMULTI(CSFVSite, IOleWindow, IOleInPlaceSite),
  591. QITABENT(CSFVSite, IOleClientSite),
  592. QITABENT(CSFVSite, IOleDocumentSite),
  593. QITABENT(CSFVSite, IServiceProvider),
  594. QITABENT(CSFVSite, IOleCommandTarget),
  595. QITABENT(CSFVSite, IDocHostUIHandler),
  596. QITABENT(CSFVSite, IOleControlSite),
  597. QITABENT(CSFVSite, IDispatch),
  598. QITABENT(CSFVSite, IInternetSecurityManager),
  599. { 0 }
  600. };
  601. return QISearch(this, qit, riid, ppv);
  602. }
  603. STDMETHODIMP_(ULONG) CSFVSite::AddRef()
  604. {
  605. return IToClass(CSFVFrame, _cSite, this)->AddRef();
  606. }
  607. STDMETHODIMP_(ULONG) CSFVSite::Release()
  608. {
  609. return IToClass(CSFVFrame, _cSite, this)->Release();
  610. }
  611. // IOleWindow
  612. STDMETHODIMP CSFVSite::GetWindow(HWND *phwnd)
  613. {
  614. CSFVFrame* pFrame = IToClass(CSFVFrame, _cSite, this);
  615. return pFrame->GetWindow(phwnd);
  616. }
  617. STDMETHODIMP CSFVSite::ContextSensitiveHelp(BOOL fEnterMode)
  618. {
  619. CSFVFrame* pFrame = IToClass(CSFVFrame, _cSite, this);
  620. return pFrame->ContextSensitiveHelp(fEnterMode);
  621. }
  622. // IInternetSecurityManager
  623. HRESULT CSFVSite::ProcessUrlAction(LPCWSTR pwszUrl, DWORD dwAction, BYTE * pPolicy, DWORD cbPolicy, BYTE * pContext, DWORD cbContext, DWORD dwFlags, DWORD dwReserved)
  624. {
  625. HRESULT hr = INET_E_DEFAULT_ACTION;
  626. if ((((URLACTION_ACTIVEX_MIN <= dwAction) &&
  627. (URLACTION_ACTIVEX_MAX >= dwAction)) ||
  628. ((URLACTION_SCRIPT_MIN <= dwAction) &&
  629. (URLACTION_SCRIPT_MAX >= dwAction))) &&
  630. pContext &&
  631. (sizeof(CLSID) == cbContext) &&
  632. (IsEqualIID(*(CLSID *) pContext, CLSID_WebViewFolderContents) ||
  633. (IsEqualIID(*(CLSID *) pContext, CLSID_ThumbCtl))))
  634. {
  635. if (EVAL(pPolicy) && EVAL(sizeof(DWORD) == cbPolicy))
  636. {
  637. *pPolicy = (DWORD) URLPOLICY_ALLOW;
  638. hr = S_OK;
  639. }
  640. else
  641. {
  642. hr = E_INVALIDARG;
  643. }
  644. }
  645. return hr;
  646. }
  647. // IOleInPlaceSite
  648. STDMETHODIMP CSFVSite::CanInPlaceActivate(void)
  649. {
  650. return S_OK;
  651. }
  652. STDMETHODIMP CSFVSite::OnInPlaceActivate(void)
  653. {
  654. TraceMsg(TF_FOCUS, "sfvf.oipa: _pAct=%x", IToClass(CSFVFrame, _cSite, this)->_pActive);
  655. IToClass(CSFVFrame, _cSite, this)->_uState = SVUIA_ACTIVATE_NOFOCUS;
  656. return S_OK;
  657. }
  658. STDMETHODIMP CSFVSite::OnUIActivate(void)
  659. {
  660. CSFVFrame* pFrame = IToClass(CSFVFrame, _cSite, this);
  661. CDefView* pView = IToClass(CDefView, _cFrame._cSite, this);
  662. HRESULT hr = pView->_OnViewWindowActive();
  663. pFrame->_uState = SVUIA_ACTIVATE_FOCUS;
  664. TraceMsg(TF_FOCUS, "sfvf.ouia: _pAct'=%x", IToClass(CSFVFrame, _cSite, this)->_pActive);
  665. return hr;
  666. }
  667. STDMETHODIMP CSFVSite::GetWindowContext(
  668. /* [out] */ IOleInPlaceFrame **ppFrame,
  669. /* [out] */ IOleInPlaceUIWindow **ppDoc,
  670. /* [out] */ LPRECT lprcPosRect,
  671. /* [out] */ LPRECT lprcClipRect,
  672. /* [out][in] */ LPOLEINPLACEFRAMEINFO lpFrameInfo)
  673. {
  674. CSFVFrame* pFrame = IToClass(CSFVFrame, _cSite, this);
  675. CDefView* pView = IToClass(CDefView, _cFrame, pFrame);
  676. *ppFrame = pFrame; pFrame->AddRef();
  677. *ppDoc = NULL; // indicating that doc window == frame window
  678. GetClientRect(pView->_hwndView, lprcPosRect);
  679. *lprcClipRect = *lprcPosRect;
  680. lpFrameInfo->fMDIApp = FALSE;
  681. lpFrameInfo->hwndFrame = pView->_hwndView; // Yes, should be view window
  682. lpFrameInfo->haccel = NULL;
  683. lpFrameInfo->cAccelEntries = 0;
  684. return S_OK;
  685. }
  686. STDMETHODIMP CSFVSite::Scroll(SIZE scrollExtant)
  687. {
  688. return S_OK;
  689. }
  690. STDMETHODIMP CSFVSite::OnUIDeactivate(BOOL fUndoable)
  691. {
  692. return S_OK;
  693. }
  694. STDMETHODIMP CSFVSite::OnInPlaceDeactivate(void)
  695. {
  696. return S_OK;
  697. }
  698. STDMETHODIMP CSFVSite::DiscardUndoState(void)
  699. {
  700. return S_OK;
  701. }
  702. STDMETHODIMP CSFVSite::DeactivateAndUndo(void)
  703. {
  704. return S_OK;
  705. }
  706. STDMETHODIMP CSFVSite::OnPosRectChange(LPCRECT lprcPosRect)
  707. {
  708. return S_OK;
  709. }
  710. // IOleClientSite
  711. STDMETHODIMP CSFVSite::SaveObject(void)
  712. {
  713. return S_OK;
  714. }
  715. STDMETHODIMP CSFVSite::GetMoniker(DWORD dwAssign, DWORD dwWhichMoniker, IMoniker **ppmk)
  716. {
  717. return E_FAIL;
  718. }
  719. STDMETHODIMP CSFVSite::GetContainer(IOleContainer **ppContainer)
  720. {
  721. *ppContainer = NULL;
  722. return E_NOTIMPL;
  723. }
  724. STDMETHODIMP CSFVSite::ShowObject(void)
  725. {
  726. return S_OK;
  727. }
  728. STDMETHODIMP CSFVSite::OnShowWindow(BOOL fShow)
  729. {
  730. return S_OK;
  731. }
  732. STDMETHODIMP CSFVSite::RequestNewObjectLayout(void)
  733. {
  734. return S_OK;
  735. }
  736. // IOleDocumentSite
  737. STDMETHODIMP CSFVSite::ActivateMe(IOleDocumentView *pviewToActivate)
  738. {
  739. CSFVFrame* pFrame = IToClass(CSFVFrame, _cSite, this);
  740. CDefView* pView = IToClass(CDefView, _cFrame, pFrame);
  741. if (pView->_uState == SVUIA_ACTIVATE_FOCUS)
  742. pviewToActivate->UIActivate(TRUE);
  743. pviewToActivate->Show(TRUE);
  744. return S_OK;
  745. }
  746. //
  747. // IOleCommandTarget stuff - just forward to _psb
  748. //
  749. STDMETHODIMP CSFVSite::QueryStatus(const GUID *pguidCmdGroup, ULONG cCmds, OLECMD rgCmds[], OLECMDTEXT *pcmdtext)
  750. {
  751. CSFVFrame* pFrame = IToClass(CSFVFrame, _cSite, this);
  752. CDefView* pView = IToClass(CDefView, _cFrame, pFrame);
  753. IOleCommandTarget* pct;
  754. HRESULT hr = OLECMDERR_E_UNKNOWNGROUP;
  755. if (SUCCEEDED(pView->_psb->QueryInterface(IID_PPV_ARG(IOleCommandTarget, &pct))))
  756. {
  757. hr = pct->QueryStatus(pguidCmdGroup, cCmds, rgCmds, pcmdtext);
  758. pct->Release();
  759. }
  760. return hr;
  761. }
  762. STDMETHODIMP CSFVSite::Exec(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANTARG *pvarargIn, VARIANTARG *pvarargOut)
  763. {
  764. CSFVFrame* pFrame = IToClass(CSFVFrame, _cSite, this);
  765. CDefView* pView = IToClass(CDefView, _cFrame, pFrame);
  766. HRESULT hr = OLECMDERR_E_UNKNOWNGROUP;
  767. if (pguidCmdGroup)
  768. {
  769. if (IsEqualIID(*pguidCmdGroup, CGID_DefView))
  770. {
  771. hr = E_INVALIDARG;
  772. if (pvarargOut)
  773. {
  774. VariantClear(pvarargOut);
  775. TCHAR szPath[MAX_PATH];
  776. switch (nCmdID)
  777. {
  778. case DVCMDID_GETTHISDIRPATH:
  779. case DVCMDID_GETTHISDIRNAME:
  780. hr = pView->_GetNameAndFlags(nCmdID == DVCMDID_GETTHISDIRPATH ?
  781. SHGDN_FORPARSING : SHGDN_INFOLDER,
  782. szPath, ARRAYSIZE(szPath), NULL);
  783. if (SUCCEEDED(hr))
  784. {
  785. hr = InitVariantFromStr(pvarargOut, szPath);
  786. }
  787. break;
  788. case DVCMDID_GETTEMPLATEDIRNAME:
  789. if (pFrame->IsWebView())
  790. {
  791. WCHAR wszMoniker[MAX_PATH];
  792. if (SUCCEEDED(pFrame->_GetCurrentWebViewMoniker(wszMoniker, ARRAYSIZE(wszMoniker))) ||
  793. SUCCEEDED(pView->_GetWebViewMoniker(wszMoniker, ARRAYSIZE(wszMoniker))))
  794. {
  795. hr = InitVariantFromStr(pvarargOut, wszMoniker);
  796. }
  797. }
  798. break;
  799. }
  800. }
  801. return hr;
  802. }
  803. else if (IsEqualIID(*pguidCmdGroup, CGID_Explorer))
  804. {
  805. if ((SBCMDID_UPDATETRAVELLOG == nCmdID) && !pView->_fCanActivateNow)
  806. {
  807. //
  808. // We get a spurious UPDATETRAVELLOG command because we have enabled
  809. // CDefviewPersistHistory to call the MSHTML IPersistHistory in webview
  810. // mode.
  811. // This seems to be the best place to fix this as the call stack
  812. // below this call is trident, and the call stack above this call is
  813. // browser code.
  814. //
  815. // The travellog is subsequently updated correctly when
  816. // CBaseBrowser2::ActivatePendingView is called.
  817. //
  818. return S_OK;
  819. }
  820. }
  821. // fall through on other cmd groups...
  822. }
  823. else if ((OLECMDID_SETTITLE == nCmdID) && !pView->_fCanActivateNow)
  824. {
  825. // NT #282632: Don't forward this message if we aren't the active view.
  826. return S_OK;
  827. }
  828. IOleCommandTarget* pct;
  829. if (SUCCEEDED(pView->_psb->QueryInterface(IID_PPV_ARG(IOleCommandTarget, &pct))))
  830. {
  831. hr = pct->Exec(pguidCmdGroup, nCmdID, nCmdexecopt, pvarargIn, pvarargOut);
  832. pct->Release();
  833. }
  834. return hr;
  835. }
  836. //*** IOleControlSite {
  837. //*** IsVK_TABCycler -- is key a TAB-equivalent
  838. // ENTRY/EXIT
  839. // dir 0 if not a TAB, non-0 if a TAB
  840. // NOTES
  841. // NYI: -1 for shift+tab, 1 for tab
  842. //
  843. int IsVK_TABCycler(MSG *pMsg)
  844. {
  845. int nDir = 0;
  846. if (!pMsg)
  847. return nDir;
  848. if (pMsg->message != WM_KEYDOWN)
  849. return nDir;
  850. if (! (pMsg->wParam == VK_TAB || pMsg->wParam == VK_F6))
  851. return nDir;
  852. nDir = (GetKeyState(VK_SHIFT) < 0) ? -1 : 1;
  853. #ifdef KEYBOARDCUES
  854. SendMessage(GetParent(pMsg->hwnd), WM_CHANGEUISTATE,
  855. MAKEWPARAM(UIS_CLEAR, UISF_HIDEFOCUS), 0);
  856. #endif
  857. return nDir;
  858. }
  859. //*** CSFVSite::TranslateAccelerator (IOCS::TranslateAccelerator)
  860. // NOTES
  861. // (following comment/logic stolen from shdocvw/dochost.cpp)
  862. // trident (or any other DO that uses IOCS::TA) calls us back when TABing
  863. // off the last link. to handle it, we flag it for our original caller
  864. // (IOIPAO::TA), and then pretend we handled it by telling trident S_OK.
  865. // trident returns S_OK to IOIPAO::TA, which checks the flag and says
  866. // 'trident did *not* handle it' by returning S_FALSE. that propagates
  867. // way up to the top where it sees it was a TAB so it does a CycleFocus.
  868. //
  869. // that's how we do it when we're top-level. when we're a frameset, we
  870. // need to do it the 'real' way, sending it up to our parent IOCS.
  871. HRESULT CSFVSite::TranslateAccelerator(MSG *pMsg, DWORD grfModifiers)
  872. {
  873. if (IsVK_TABCycler(pMsg))
  874. {
  875. CSFVFrame* pFrame = IToClass(CSFVFrame, _cSite, this);
  876. CDefView* pView = IToClass(CDefView, _cFrame, pFrame);
  877. TraceMsg(TF_FOCUS, "csfvs::IOCS::TA(wParam=VK_TAB) ret _fCycleFocus=TRUE hr=S_OK (lie)");
  878. // defer it, set flag for cdv::IOIPAO::TA, and pretend we handled it
  879. ASSERT(!pView->_fCycleFocus);
  880. pView->_fCycleFocus = TRUE;
  881. return S_OK;
  882. }
  883. //ASSERT(!pView->_fCycleFocus);
  884. return S_FALSE;
  885. }
  886. // }
  887. // IServiceProvider
  888. HRESULT CSFVSite::QueryService(REFGUID guidService, REFIID riid, void ** ppv)
  889. {
  890. CSFVFrame* pFrame = IToClass(CSFVFrame, _cSite, this);
  891. CDefView* pView = IToClass(CDefView, _cFrame, pFrame);
  892. *ppv = NULL;
  893. HRESULT hr = E_FAIL;
  894. if (guidService == SID_DefView)
  895. {
  896. if (riid == IID_IDefViewFrame && pView->_IsDesktop())
  897. {
  898. return E_FAIL;
  899. }
  900. // Try site QI
  901. hr = QueryInterface(riid, ppv);
  902. }
  903. if (FAILED(hr))
  904. {
  905. // Delegate to defview QS
  906. hr = pView->QueryService(guidService, riid, ppv);
  907. if (FAILED(hr))
  908. {
  909. // Look for IID_IInternetSecurityManager
  910. if (guidService == IID_IInternetSecurityManager)
  911. {
  912. ASSERT(riid == IID_IInternetSecurityManager);
  913. hr = QueryInterface(riid, ppv);
  914. }
  915. }
  916. }
  917. return hr;
  918. }
  919. HRESULT CSFVSite::Invoke(DISPID dispidMember, REFIID iid, LCID lcid, WORD wFlags, DISPPARAMS *pdispparams,
  920. VARIANT *pVarResult, EXCEPINFO *pexcepinfo, UINT *puArgErr)
  921. {
  922. if (!pVarResult)
  923. return E_INVALIDARG;
  924. //Get pointer to the defview
  925. CSFVFrame* pFrame = IToClass(CSFVFrame, _cSite, this);
  926. CDefView* pView = IToClass(CDefView, _cFrame, pFrame);
  927. // We handle the query of whether we want to show images, ourselves.
  928. if (wFlags == DISPATCH_PROPERTYGET)
  929. {
  930. switch (dispidMember)
  931. {
  932. case DISPID_AMBIENT_DLCONTROL:
  933. {
  934. // Do the following only if this is NOT the desktop.
  935. // (Because Desktop is in offline mode, it should
  936. // return DLCTL_OFFLINEIFNOTCONNECTED flag). The following code
  937. // should be executed only for NON-desktop folders.
  938. if (!(pView->_IsDesktop()))
  939. {
  940. pVarResult->vt = VT_I4;
  941. pVarResult->lVal = DLCTL_DLIMAGES | DLCTL_VIDEOS;
  942. return S_OK;
  943. }
  944. }
  945. }
  946. }
  947. // We delegate all other queries to shdocvw.
  948. if (!_peds)
  949. {
  950. IUnknown_QueryService(pView->_psb, IID_IExpDispSupport, IID_PPV_ARG(IExpDispSupport, &_peds));
  951. }
  952. if (!_peds)
  953. return E_NOTIMPL;
  954. return _peds->OnInvoke(dispidMember, iid, lcid, wFlags, pdispparams, pVarResult, pexcepinfo, puArgErr);
  955. }
  956. HRESULT CHostDropTarget::QueryInterface(REFIID riid, void **ppv)
  957. {
  958. static const QITAB qit[] = {
  959. QITABENT(CHostDropTarget, IDropTarget), // IID_IDropTarget
  960. { 0 }
  961. };
  962. return QISearch(this, qit, riid, ppv);
  963. }
  964. ULONG CHostDropTarget::AddRef(void)
  965. {
  966. CSFVSite* pcsfvs = IToClass(CSFVSite, _dt, this);
  967. return pcsfvs->AddRef();
  968. }
  969. ULONG CHostDropTarget::Release(void)
  970. {
  971. CSFVSite* pcsfvs = IToClass(CSFVSite, _dt, this);
  972. return pcsfvs->Release();
  973. }
  974. HRESULT CHostDropTarget::DragEnter(IDataObject *pdtobj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
  975. {
  976. return _pdtFrame->DragEnter(pdtobj, grfKeyState, pt, pdwEffect);
  977. }
  978. HRESULT CHostDropTarget::DragOver(DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
  979. {
  980. return _pdtFrame->DragOver(grfKeyState, pt, pdwEffect);
  981. }
  982. HRESULT CHostDropTarget::DragLeave(void)
  983. {
  984. return _pdtFrame->DragLeave();
  985. }
  986. HRESULT CHostDropTarget::Drop(IDataObject *pdtobj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
  987. {
  988. return _pdtFrame->Drop(pdtobj, grfKeyState, pt, pdwEffect);
  989. }
  990. STDMETHODIMP CSFVFrame::QueryInterface(REFIID riid, void **ppv)
  991. {
  992. static const QITAB qit[] = {
  993. QITABENTMULTI(CSFVFrame, IOleWindow, IOleInPlaceFrame), // IID_IOleWindow
  994. QITABENTMULTI(CSFVFrame, IOleInPlaceUIWindow, IOleInPlaceFrame), // IID_IOleInPlaceUIWindow
  995. QITABENT(CSFVFrame, IOleInPlaceFrame), // IID_IOleInPlaceFrame
  996. QITABENT(CSFVFrame, IAdviseSink), // IID_IAdviseSink
  997. QITABENT(CSFVFrame, IPropertyNotifySink), // IID_IPropertyNotifySink
  998. { 0 }
  999. };
  1000. return QISearch(this, qit, riid, ppv);
  1001. }
  1002. STDMETHODIMP_(ULONG) CSFVFrame::AddRef()
  1003. {
  1004. CDefView* pView = IToClass(CDefView, _cFrame, this);
  1005. return pView->AddRef();
  1006. }
  1007. STDMETHODIMP_(ULONG) CSFVFrame::Release()
  1008. {
  1009. CDefView* pView = IToClass(CDefView, _cFrame, this);
  1010. return pView->Release();
  1011. }
  1012. // IOleWindow
  1013. STDMETHODIMP CSFVFrame::GetWindow(HWND *phwnd)
  1014. {
  1015. CDefView* pView = IToClass(CDefView, _cFrame, this);
  1016. return pView->GetWindow(phwnd);
  1017. }
  1018. STDMETHODIMP CSFVFrame::ContextSensitiveHelp(BOOL fEnterMode)
  1019. {
  1020. CDefView* pView = IToClass(CDefView, _cFrame, this);
  1021. return pView->ContextSensitiveHelp(fEnterMode);
  1022. }
  1023. // IOleInPlaceUIWindow
  1024. STDMETHODIMP CSFVFrame::GetBorder(LPRECT lprectBorder)
  1025. {
  1026. CDefView* pView = IToClass(CDefView, _cFrame, this);
  1027. GetClientRect(pView->_hwndView, lprectBorder);
  1028. return S_OK;
  1029. }
  1030. STDMETHODIMP CSFVFrame::RequestBorderSpace(LPCBORDERWIDTHS pborderwidths)
  1031. {
  1032. return INPLACE_E_NOTOOLSPACE;
  1033. }
  1034. STDMETHODIMP CSFVFrame::SetBorderSpace(LPCBORDERWIDTHS pborderwidths)
  1035. {
  1036. return INPLACE_E_NOTOOLSPACE;
  1037. }
  1038. STDMETHODIMP CSFVFrame::SetActiveObject(IOleInPlaceActiveObject *pActiveObject, LPCOLESTR pszObjName)
  1039. {
  1040. TraceMsg(TF_FOCUS, "sfvf.sao(pAct'=%x): _pAct=%x", pActiveObject, _pActive);
  1041. if (pActiveObject != _pActive)
  1042. {
  1043. IAdviseSink* pOurSink = SAFECAST(this, IAdviseSink*);
  1044. #ifdef DEBUG
  1045. QueryInterface(IID_PPV_ARG(IAdviseSink, &pOurSink));
  1046. #endif
  1047. if (_pActive)
  1048. {
  1049. //
  1050. // if we had an OLE view object then disconnect our advise sink and
  1051. // release the view object.
  1052. //
  1053. if (_pvoActive)
  1054. {
  1055. IAdviseSink *pSink;
  1056. if (SUCCEEDED(_pvoActive->GetAdvise(NULL, NULL, &pSink)))
  1057. {
  1058. // Be polite, only blow away the advise if we're the
  1059. // one who's listening
  1060. if (pSink == pOurSink)
  1061. {
  1062. _pvoActive->SetAdvise(0, 0, NULL);
  1063. }
  1064. // If there was no sink, GetAdvise succeeds but sets
  1065. // pSink to NULL, so need to check pSink here.
  1066. if (pSink)
  1067. pSink->Release();
  1068. }
  1069. ATOMICRELEASE(_pvoActive);
  1070. }
  1071. ATOMICRELEASE(_pActive);
  1072. }
  1073. _pActive = pActiveObject;
  1074. if (_pActive)
  1075. {
  1076. _pActive->AddRef();
  1077. //
  1078. // try to get an OLE view object and set up an advisory connection.
  1079. //
  1080. if (SUCCEEDED(_pActive->QueryInterface(IID_PPV_ARG(IViewObject, &_pvoActive))))
  1081. {
  1082. ASSERT(_pvoActive);
  1083. _pvoActive->SetAdvise(DVASPECT_CONTENT, 0, pOurSink);
  1084. }
  1085. }
  1086. //
  1087. // since we changed the active view, tell our owner that the content
  1088. // may have changed...
  1089. //
  1090. OnViewChange(DVASPECT_CONTENT, -1);
  1091. #ifdef DEBUG
  1092. ATOMICRELEASE(pOurSink);
  1093. #endif
  1094. }
  1095. return S_OK;
  1096. }
  1097. // IOleInPlaceFrame
  1098. STDMETHODIMP CSFVFrame::InsertMenus(HMENU hmenuShared, LPOLEMENUGROUPWIDTHS lpMenuWidths)
  1099. {
  1100. if (hmenuShared)
  1101. {
  1102. // No menu merging
  1103. // or fill lpMenuWidths with 0 and return success
  1104. lpMenuWidths->width[0] = 0;
  1105. lpMenuWidths->width[2] = 0;
  1106. lpMenuWidths->width[4] = 0;
  1107. }
  1108. return S_OK;
  1109. }
  1110. STDMETHODIMP CSFVFrame::SetMenu(HMENU hmenuShared, HOLEMENU holemenu, HWND hwndActiveObject)
  1111. {
  1112. return S_OK; // No menu merging
  1113. }
  1114. STDMETHODIMP CSFVFrame::RemoveMenus(HMENU hmenuShared)
  1115. {
  1116. return E_FAIL; // No menu merging
  1117. }
  1118. //
  1119. // This one is a bit tricky. If the client wants to clear the status
  1120. // area, then restore it to the original defview status area text.
  1121. //
  1122. // For example, in webview, MSHTML will keep clearing the status area
  1123. // whenever you are not over a link, which would otherwise keep erasing
  1124. // the "n object(s) selected" message from defview.
  1125. //
  1126. // To really clear the status area, set the text to " " instead of "".
  1127. //
  1128. STDMETHODIMP CSFVFrame::SetStatusText(LPCOLESTR pszStatusText)
  1129. {
  1130. CDefView* pView = IToClass(CDefView, _cFrame, this);
  1131. if (pszStatusText && pszStatusText[0])
  1132. return pView->_psb->SetStatusTextSB(pszStatusText);
  1133. pView->_UpdateStatusBar(FALSE);
  1134. return S_OK;
  1135. }
  1136. STDMETHODIMP CSFVFrame::EnableModeless(BOOL fEnable)
  1137. {
  1138. CDefView* pView = IToClass(CDefView, _cFrame, this);
  1139. if (pView->_IsDesktop())
  1140. {
  1141. if (fEnable)
  1142. {
  1143. pView->_fDesktopModal = FALSE;
  1144. if (pView->_fDesktopRefreshPending) //Was a refresh pending?
  1145. {
  1146. pView->_fDesktopRefreshPending = FALSE;
  1147. //Let's do a refresh asynchronously.
  1148. PostMessage(pView->_hwndView, WM_KEYDOWN, (WPARAM)VK_F5, 0);
  1149. }
  1150. TraceMsg(TF_DEFVIEW, "A Modal dlg is going away!");
  1151. }
  1152. else
  1153. {
  1154. pView->_fDesktopModal = TRUE;
  1155. TraceMsg(TF_DEFVIEW, "A Modal dlg is coming up for Desktop!");
  1156. }
  1157. }
  1158. return pView->_psb->EnableModelessSB(fEnable);
  1159. }
  1160. STDMETHODIMP CSFVFrame::TranslateAccelerator(LPMSG lpmsg,WORD wID)
  1161. {
  1162. CDefView* pView = IToClass(CDefView, _cFrame, this);
  1163. return pView->_psb->TranslateAcceleratorSB(lpmsg, wID);
  1164. }
  1165. // IAdviseSink
  1166. void CSFVFrame::OnDataChange(FORMATETC *, STGMEDIUM *)
  1167. {
  1168. }
  1169. void CSFVFrame::OnViewChange(DWORD dwAspect, LONG lindex)
  1170. {
  1171. if (IsWebView() && _pvoActive)
  1172. {
  1173. CDefView *pView = IToClass(CDefView, _cFrame, this);
  1174. pView->PropagateOnViewChange(dwAspect, lindex);
  1175. }
  1176. }
  1177. void CSFVFrame::OnRename(IMoniker *)
  1178. {
  1179. }
  1180. void CSFVFrame::OnSave()
  1181. {
  1182. }
  1183. void CSFVFrame::OnClose()
  1184. {
  1185. if (IsWebView() && _pvoActive)
  1186. {
  1187. CDefView *pView = IToClass(CDefView, _cFrame, this);
  1188. pView->PropagateOnClose();
  1189. }
  1190. }
  1191. HRESULT CSFVFrame::OnChanged(DISPID dispid)
  1192. {
  1193. if (DISPID_READYSTATE == dispid || DISPID_UNKNOWN == dispid)
  1194. {
  1195. ASSERT(_pOleObjReadyState);
  1196. if (!_pOleObjReadyState)
  1197. return S_OK; //Documentation says we need to return this all the time
  1198. IDispatch *pdisp;
  1199. if (SUCCEEDED(_pOleObjReadyState->QueryInterface(IID_PPV_ARG(IDispatch, &pdisp))))
  1200. {
  1201. CDefView* pView = IToClass(CDefView, _cFrame, this);
  1202. EXCEPINFO exInfo;
  1203. VARIANTARG va = {0};
  1204. DISPPARAMS dp = {0};
  1205. if (EVAL(SUCCEEDED(pdisp->Invoke(DISPID_READYSTATE, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET, &dp, &va, &exInfo, NULL))
  1206. && va.vt == VT_I4))
  1207. {
  1208. if (va.lVal >= READYSTATE_INTERACTIVE)
  1209. {
  1210. if (!_fReadyStateInteractiveProcessed)
  1211. {
  1212. _fReadyStateInteractiveProcessed = TRUE;
  1213. // First time through this function we need to request
  1214. // activation. After that, we can switch immediately.
  1215. //
  1216. // Switch the bit early since SHDVID_ACTIVATEMENOW calls
  1217. // SHDVID_CANACTIVATENOW which checks it.
  1218. //
  1219. BOOL fTmp = !pView->_fCanActivateNow;
  1220. pView->_fCanActivateNow = TRUE;
  1221. if (fTmp)
  1222. {
  1223. // If we did an async CreateViewWindow2, then we
  1224. // need to notify the browser that we're ready
  1225. // to be activated - it will uiactivate us which
  1226. // will cause us to switch.
  1227. //Don't Make the View Visible, if it is in
  1228. //DEACTIVATE State. The View would be made visible
  1229. //during uiactivate call. - KishoreP
  1230. if (pView->_uState != SVUIA_DEACTIVATE)
  1231. {
  1232. SetWindowPos(pView->_hwndView, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE|SWP_SHOWWINDOW);
  1233. }
  1234. IUnknown_Exec(pView->_psb, &CGID_ShellDocView, SHDVID_ACTIVATEMENOW, NULL, NULL, NULL);
  1235. }
  1236. else
  1237. {
  1238. // Technically we only want to do this iff our view is currently
  1239. // the active visible view. !fCanActivateNow => we are definitely not visible,
  1240. // but _fCanActivateNow does NOT imply visible, it implies we are ready to be
  1241. // made the active visible guy, and that we've requested to be made the active
  1242. // visible view, but not necessarily that we *are* the active visible view. If
  1243. // the previous view wasn't ready to go away, then we are in limbo. But if that's
  1244. // the case, then our menus aren't merged, so there's no way the user could
  1245. // switch views on us... Verify this.
  1246. #ifdef DEBUG
  1247. CDefView* pView = IToClass(CDefView, _cFrame, this);
  1248. IShellView* psvCurrent;
  1249. if (EVAL(SUCCEEDED(pView->_psb->QueryActiveShellView(&psvCurrent))))
  1250. {
  1251. ASSERT(SHIsSameObject(SAFECAST(pView, IShellView2*), psvCurrent));
  1252. psvCurrent->Release();
  1253. }
  1254. ASSERT(pView->_uState != SVUIA_DEACTIVATE)
  1255. #endif
  1256. // If we're simply switching views, go ahead
  1257. // and do it.
  1258. _SwitchToNewOleObj();
  1259. }
  1260. if (g_dwProfileCAP & 0x00010000)
  1261. StopCAP();
  1262. }
  1263. }
  1264. }
  1265. if (va.lVal == READYSTATE_COMPLETE)
  1266. {
  1267. _UpdateZonesStatusPane(_pOleObjReadyState);
  1268. _RemoveReadyStateNotifyCapability();
  1269. _fReadyStateComplete = TRUE;
  1270. }
  1271. pdisp->Release();
  1272. }
  1273. }
  1274. return S_OK;
  1275. }
  1276. HRESULT CSFVFrame::OnRequestEdit(DISPID dispid)
  1277. {
  1278. return E_NOTIMPL;
  1279. }
  1280. // randum stuff
  1281. HRESULT CSFVFrame::GetCommandTarget(IOleCommandTarget** ppct)
  1282. {
  1283. if (_pDocView)
  1284. {
  1285. return _pDocView->QueryInterface(IID_PPV_ARG(IOleCommandTarget, ppct));
  1286. }
  1287. *ppct = NULL;
  1288. return E_FAIL;
  1289. }
  1290. HRESULT CSFVFrame::SetRect(LPRECT prc)
  1291. {
  1292. if (IsWebView() && _pDocView)
  1293. return _pDocView->SetRect(prc);
  1294. return E_FAIL;
  1295. }
  1296. HRESULT CSFVFrame::OnTranslateAccelerator(LPMSG pmsg, BOOL* pbTabOffLastTridentStop)
  1297. {
  1298. HRESULT hr = E_FAIL;
  1299. *pbTabOffLastTridentStop = FALSE;
  1300. if (IsWebView())
  1301. {
  1302. if (_pActive)
  1303. {
  1304. hr = _pActive->TranslateAccelerator(pmsg);
  1305. }
  1306. else if (_pOleObj)
  1307. {
  1308. IOleInPlaceActiveObject* pIAO;
  1309. if (SUCCEEDED(_pOleObj->QueryInterface(IID_PPV_ARG(IOleInPlaceActiveObject, &pIAO))))
  1310. {
  1311. hr = pIAO->TranslateAccelerator(pmsg);
  1312. pIAO->Release();
  1313. }
  1314. }
  1315. if (hr == S_OK)
  1316. {
  1317. CDefView* pView = IToClass(CDefView, _cFrame, this);
  1318. if (pView->_fCycleFocus)
  1319. {
  1320. // we got called back by trident (IOCS::TA), but deferred it.
  1321. // time to pay the piper.
  1322. *pbTabOffLastTridentStop = TRUE;
  1323. TraceMsg(TF_FOCUS, "sfvf::IOIPAO::OnTA piao->TA==S_OK ret _fCycleFocus=FALSE hr=S_FALSE (piper)");
  1324. pView->_fCycleFocus = FALSE;
  1325. // _UIActivateIO(FALSE, NULL);
  1326. hr = S_FALSE; // time to pay the piper
  1327. }
  1328. }
  1329. ASSERT(! IToClass(CDefView, _cFrame, this)->_fCycleFocus);
  1330. }
  1331. return hr;
  1332. }
  1333. HRESULT CSFVFrame::_HasFocusIO()
  1334. {
  1335. TraceMsg(TF_FOCUS, "sfvf._hfio: uState=%x hr=%x", _uState, (_uState == SVUIA_ACTIVATE_FOCUS) ? S_OK : S_FALSE);
  1336. if (IsWebView())
  1337. {
  1338. return (_uState == SVUIA_ACTIVATE_FOCUS) ? S_OK : S_FALSE;
  1339. }
  1340. return S_FALSE;
  1341. }
  1342. HRESULT CSFVFrame::_UIActivateIO(BOOL fActivate, MSG *pMsg)
  1343. {
  1344. HRESULT hr;
  1345. if (IsWebView() && _pOleObj)
  1346. {
  1347. CSFVFrame* pFrame = IToClass(CSFVFrame, _cSite, this);
  1348. CDefView* pView = IToClass(CDefView, _cFrame, pFrame);
  1349. LONG iVerb;
  1350. RECT rcView;
  1351. if (fActivate)
  1352. {
  1353. iVerb = OLEIVERB_UIACTIVATE;
  1354. _uState = SVUIA_ACTIVATE_FOCUS;
  1355. }
  1356. else
  1357. {
  1358. iVerb = OLEIVERB_INPLACEACTIVATE;
  1359. _uState = SVUIA_ACTIVATE_NOFOCUS;
  1360. }
  1361. if (fActivate)
  1362. {
  1363. GetClientRect(pView->_hwndView, &rcView);
  1364. hr = _pOleObj->DoVerb(iVerb, pMsg,
  1365. &_cSite, (UINT)-1, pView->_hwndView, &rcView);
  1366. }
  1367. else
  1368. {
  1369. IOleInPlaceObject *pipo;
  1370. hr = _pOleObj->QueryInterface(IID_PPV_ARG(IOleInPlaceObject, &pipo));
  1371. if (SUCCEEDED(hr))
  1372. {
  1373. hr = pipo->UIDeactivate();
  1374. pipo->Release();
  1375. }
  1376. }
  1377. ASSERT(SUCCEEDED(hr));
  1378. ASSERT(_uState == (UINT)(fActivate ? SVUIA_ACTIVATE_FOCUS : SVUIA_ACTIVATE_NOFOCUS));
  1379. TraceMsg(TF_FOCUS, "sfvf._uiaio(fAct=%d) ExtView DoVerb S_OK", fActivate);
  1380. hr = S_OK;
  1381. }
  1382. else
  1383. {
  1384. TraceMsg(TF_FOCUS, "sfvf._uiaio(fAct=%d) else S_FALSE", fActivate);
  1385. hr = S_FALSE;
  1386. }
  1387. return hr;
  1388. }