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

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