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.

891 lines
28 KiB

  1. #include "stdafx.h"
  2. #pragma hdrstop
  3. #include "stdenum.h"
  4. #include <mshtmdid.h>
  5. #include "..\util.h"
  6. #define SZ_ATL_SHEMBEDDING_WNDCLASS TEXT("ATL Shell Embedding")
  7. HRESULT MakeSafeForScripting(IUnknown** ppDisp);
  8. class ATL_NO_VTABLE CWebViewFolderContents
  9. : public CComObjectRootEx<CComSingleThreadModel>
  10. , public CComCoClass<CWebViewFolderContents, &CLSID_WebViewFolderContents>
  11. , public CComControl<CWebViewFolderContents>
  12. , public IDispatchImpl<IShellFolderViewDual2, &IID_IShellFolderViewDual2, &LIBID_Shell32, 1, 0, CComTypeInfoHolder>
  13. , public IProvideClassInfo2Impl<&CLSID_WebViewFolderContents, NULL, &LIBID_Shell32, 1, 0, CComTypeInfoHolder>
  14. , public IPersistImpl<CWebViewFolderContents>
  15. , public IOleControlImpl<CWebViewFolderContents>
  16. , public IOleObjectImpl<CWebViewFolderContents>
  17. , public IViewObjectExImpl<CWebViewFolderContents>
  18. , public IOleInPlaceActiveObjectImpl<CWebViewFolderContents>
  19. , public IDataObjectImpl<CWebViewFolderContents>
  20. , public IObjectSafetyImpl<CWebViewFolderContents, INTERFACESAFE_FOR_UNTRUSTED_CALLER>
  21. , public IConnectionPointContainer
  22. , public IOleInPlaceObject
  23. , public IInternetSecurityMgrSite
  24. , public IServiceProvider
  25. {
  26. public:
  27. CWebViewFolderContents();
  28. ~CWebViewFolderContents();
  29. DECLARE_POLY_AGGREGATABLE(CWebViewFolderContents);
  30. DECLARE_NO_REGISTRY();
  31. DECLARE_WND_CLASS(SZ_ATL_SHEMBEDDING_WNDCLASS)
  32. BEGIN_COM_MAP(CWebViewFolderContents)
  33. // ATL Uses these in IUnknown::QueryInterface()
  34. COM_INTERFACE_ENTRY_IID(IID_IViewObject, IViewObjectEx)
  35. COM_INTERFACE_ENTRY_IID(IID_IViewObject2, IViewObjectEx)
  36. COM_INTERFACE_ENTRY(IViewObjectEx)
  37. COM_INTERFACE_ENTRY_IID(IID_IOleWindow, IOleInPlaceActiveObject)
  38. COM_INTERFACE_ENTRY(IOleInPlaceActiveObject)
  39. COM_INTERFACE_ENTRY(IOleInPlaceObject)
  40. COM_INTERFACE_ENTRY(IDispatch)
  41. COM_INTERFACE_ENTRY(IProvideClassInfo2)
  42. COM_INTERFACE_ENTRY(IProvideClassInfo)
  43. COM_INTERFACE_ENTRY(IOleControl)
  44. COM_INTERFACE_ENTRY(IOleObject)
  45. COM_INTERFACE_ENTRY(IDataObject)
  46. COM_INTERFACE_ENTRY(IObjectSafety)
  47. COM_INTERFACE_ENTRY(IConnectionPointContainer)
  48. COM_INTERFACE_ENTRY(IShellFolderViewDual)
  49. COM_INTERFACE_ENTRY(IShellFolderViewDual2)
  50. COM_INTERFACE_ENTRY(IServiceProvider)
  51. COM_INTERFACE_ENTRY(IPersist)
  52. COM_INTERFACE_ENTRY(IInternetSecurityMgrSite)
  53. END_COM_MAP()
  54. // Declare the default message map
  55. BEGIN_MSG_MAP(CWebViewFolderContents)
  56. MESSAGE_HANDLER(WM_SIZE, _OnSizeMessage)
  57. MESSAGE_HANDLER(WM_NOTIFY, _OnMessageForwarder)
  58. MESSAGE_HANDLER(WM_CONTEXTMENU, _OnMessageForwarder)
  59. MESSAGE_HANDLER(WM_SETCURSOR, _OnMessageForwarder)
  60. MESSAGE_HANDLER(WM_ERASEBKGND, _OnEraseBkgndMessage)
  61. END_MSG_MAP()
  62. // IDispatch
  63. STDMETHODIMP Invoke(DISPID dispidMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS * pdispparams, VARIANT * pvarResult, EXCEPINFO * pexcepinfo, UINT * puArgErr);
  64. STDMETHODIMP GetTypeInfo(UINT itinfo, LCID lcid, ITypeInfo** pptinfo);
  65. STDMETHODIMP GetIDsOfNames(REFIID riid, OLECHAR **rgszNames, UINT cNames, LCID lcid, DISPID * rgdispid);
  66. // IProvideClassInfo
  67. STDMETHODIMP GetClassInfo(ITypeInfo** pptinfo);
  68. // IServiceProvider
  69. STDMETHODIMP QueryService(REFGUID guidService, REFIID riid, void **ppvObj);
  70. // IInternetSecurityMgrSite
  71. // STDMETHODIMP GetWindow(HWND * lphwnd); // Also in IOleWindow
  72. STDMETHODIMP EnableModeless(BOOL fEnable) { return IOleInPlaceActiveObjectImpl<CWebViewFolderContents>::EnableModeless(fEnable); }; // Also in IOleInPlaceActiveObject
  73. // IShellFolderViewDual2
  74. STDMETHODIMP get_Application(IDispatch **ppid);
  75. STDMETHODIMP get_Parent(IDispatch **ppid);
  76. STDMETHODIMP get_Folder(Folder **ppid);
  77. STDMETHODIMP SelectedItems(FolderItems **ppid);
  78. STDMETHODIMP get_FocusedItem(FolderItem **ppid);
  79. STDMETHODIMP SelectItem(VARIANT *pvfi, int dwFlags);
  80. STDMETHODIMP PopupItemMenu(FolderItem * pfi, VARIANT vx, VARIANT vy, BSTR * pbs);
  81. STDMETHODIMP get_Script(IDispatch **ppid);
  82. STDMETHODIMP get_ViewOptions(long *plSetting);
  83. STDMETHODIMP get_CurrentViewMode(UINT *pViewMode);
  84. STDMETHODIMP put_CurrentViewMode(UINT ViewMode);
  85. STDMETHODIMP SelectItemRelative(int iRelative);
  86. // IOleWindow
  87. STDMETHODIMP GetWindow(HWND * lphwnd) { return IOleInPlaceActiveObjectImpl<CWebViewFolderContents>::GetWindow(lphwnd); };
  88. STDMETHODIMP ContextSensitiveHelp(BOOL fEnterMode) { return IOleInPlaceActiveObjectImpl<CWebViewFolderContents>::ContextSensitiveHelp(fEnterMode); };
  89. // IOleObject
  90. STDMETHODIMP GetMiscStatus(DWORD dwAspect, DWORD *pdwStatus);
  91. STDMETHODIMP SetClientSite(IOleClientSite *pClientSite)
  92. {
  93. if (pClientSite == NULL)
  94. {
  95. // Unadvise
  96. if (m_spClientSite)
  97. {
  98. AtlUnadvise(m_spClientSite, IID_IDispatch, _dwHtmlWindowAdviseCookie);
  99. _dwHtmlWindowAdviseCookie = 0;
  100. }
  101. }
  102. // Call the default impl first
  103. HRESULT hr = IOleObjectImpl<CWebViewFolderContents>::SetClientSite(pClientSite);
  104. if (m_spClientSite && SUCCEEDED(hr))
  105. {
  106. CComPtr<IOleContainer> spContainer;
  107. if (m_spClientSite->GetContainer(&spContainer) == S_OK)
  108. {
  109. CComPtr<IHTMLDocument2> spDocument2;
  110. if (spContainer->QueryInterface(&spDocument2) == S_OK)
  111. {
  112. CComPtr<IHTMLWindow2> spHTMLWindow2;
  113. if (spDocument2->get_parentWindow(&spHTMLWindow2) == S_OK)
  114. {
  115. // Now we AtlAdvise
  116. CComPtr<IUnknown> spUnk;
  117. ControlQueryInterface(IID_PPV_ARG(IUnknown, &spUnk));
  118. AtlAdvise(spHTMLWindow2, spUnk, IID_IDispatch, &_dwHtmlWindowAdviseCookie);
  119. }
  120. }
  121. }
  122. }
  123. return hr;
  124. }
  125. // IOleInPlaceObject
  126. STDMETHODIMP InPlaceDeactivate(void);
  127. STDMETHODIMP UIDeactivate(void) { return IOleInPlaceObject_UIDeactivate(); };
  128. STDMETHODIMP SetObjectRects(LPCRECT lprcPosRect, LPCRECT lprcClipRect);
  129. STDMETHODIMP ReactivateAndUndo(void) { return E_NOTIMPL; };
  130. // IOleInPlaceActiveObject
  131. // our frame was activated, better do the activation thing.
  132. STDMETHODIMP OnFrameWindowActivate(BOOL fActivate)
  133. {
  134. if (_hwndLV && fActivate)
  135. ::SetFocus(_hwndLV);
  136. return S_OK;
  137. };
  138. STDMETHODIMP TranslateAccelerator(LPMSG pMsg);
  139. // IConnectionPointContainer
  140. STDMETHODIMP EnumConnectionPoints(IEnumConnectionPoints **ppEnum);
  141. STDMETHODIMP FindConnectionPoint(REFIID riid, IConnectionPoint **ppCP);
  142. // Over ride ATL functions.
  143. LRESULT _OnMessageForwarder(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL & bHandled);
  144. LRESULT _OnEraseBkgndMessage(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL & bHandled);
  145. LRESULT _OnSizeMessage(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL & bHandled);
  146. HRESULT DoVerbUIActivate(LPCRECT prcPosRect, HWND hwndParent);
  147. HRESULT DoVerbInPlaceActivate(LPCRECT prcPosRect, HWND hwndParent);
  148. STDMETHODIMP Close(DWORD dwSaveOption);
  149. protected:
  150. // Helper functions;
  151. HRESULT _SetupAutomationForwarders(void);
  152. HRESULT _ReleaseAutomationForwarders(void);
  153. HRESULT _OnInPlaceActivate(void);
  154. void _ReleaseWindow(void);
  155. void _ShowWindowLV(HWND hwndLV);
  156. void _UnadviseAll();
  157. class CConnectionPointForwarder : public IConnectionPoint
  158. {
  159. // IUnknown methods
  160. STDMETHODIMP QueryInterface(REFIID riid, void **ppvObj);
  161. STDMETHODIMP_(ULONG) AddRef(void);
  162. STDMETHODIMP_(ULONG) Release(void);
  163. // IConnectionPoint methods
  164. STDMETHODIMP GetConnectionInterface(IID * pIID);
  165. STDMETHODIMP GetConnectionPointContainer(IConnectionPointContainer ** ppCPC);
  166. STDMETHODIMP Advise(LPUNKNOWN pUnkSink, DWORD * pdwCookie);
  167. STDMETHODIMP Unadvise(DWORD dwCookie);
  168. STDMETHODIMP EnumConnections(LPENUMCONNECTIONS * ppEnum) { return _pcpAuto->EnumConnections(ppEnum); }
  169. IConnectionPoint * _pcpAuto;
  170. HDSA _dsaCookies;
  171. IUnknown* _punkParent;
  172. friend class CWebViewFolderContents;
  173. };
  174. friend class CConnectionPointForwarder;
  175. CConnectionPointForwarder m_cpEvents;
  176. IDefViewFrame3* _pdvf3; // defview
  177. BOOL _fClientEdge;
  178. BOOL _fTabRecieved;
  179. BOOL _fCalledOnSizeForThisSize;
  180. HWND _hwndLV;
  181. HWND _hwndLVParent;
  182. ITypeInfo * _pClassTypeInfo; // ITypeInfo of class
  183. DWORD _dwHtmlWindowAdviseCookie;
  184. // stuff added to delegate all of our work up to DefViews automation
  185. IShellFolderViewDual2 *_pdispAuto;
  186. };
  187. LCID g_lcidLocaleUnicpp = MAKELCID(LANG_USER_DEFAULT, SORT_DEFAULT);
  188. CWebViewFolderContents::CWebViewFolderContents()
  189. {
  190. DllAddRef();
  191. // This allocator should have zero inited the memory, so assert the member variables are empty.
  192. ASSERT(!_pdvf3);
  193. ASSERT(!_hwndLV);
  194. ASSERT(!_hwndLVParent);
  195. ASSERT(!_fClientEdge);
  196. ASSERT(!_fTabRecieved);
  197. ASSERT(!_pClassTypeInfo);
  198. ASSERT(!m_cpEvents._dsaCookies);
  199. ASSERT(!_fCalledOnSizeForThisSize);
  200. m_bWindowOnly = TRUE;
  201. m_bEnabled = TRUE;
  202. m_bResizeNatural = TRUE;
  203. m_cpEvents._punkParent = SAFECAST(this, IViewObjectEx *);
  204. GetWndClassInfo().m_wc.style &= ~(CS_HREDRAW|CS_VREDRAW);
  205. }
  206. CWebViewFolderContents::~CWebViewFolderContents()
  207. {
  208. _UnadviseAll();
  209. ASSERT(NULL == _pdvf3);
  210. ASSERT(NULL == _hwndLV);
  211. if (_pClassTypeInfo)
  212. _pClassTypeInfo->Release();
  213. ATOMICRELEASE(_pdvf3);
  214. _ReleaseAutomationForwarders();
  215. DllRelease();
  216. }
  217. // ATL maintainence functions
  218. LRESULT CWebViewFolderContents::_OnMessageForwarder(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL & bHandled)
  219. {
  220. if (_hwndLVParent)
  221. {
  222. bHandled = TRUE;
  223. HWND hwnd = NULL;
  224. // Forward these messages directly to DefView (don't let MSHTML eat them)
  225. return ::SendMessage(_hwndLVParent, uMsg, wParam, lParam);
  226. }
  227. else
  228. return 0;
  229. }
  230. LRESULT CWebViewFolderContents::_OnEraseBkgndMessage(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL & bHandled)
  231. {
  232. // This function will just tell the default handler not to do anything and we
  233. // will handle it.
  234. // This is done in the case of WM_ERASEBKGND to...
  235. // Avoid flicker by not erasing the background. This OC doesn't care
  236. // about design-time issues - just usage on a Web View page.
  237. bHandled = TRUE;
  238. return 1;
  239. }
  240. LRESULT CWebViewFolderContents::_OnSizeMessage(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL & bHandled)
  241. {
  242. // Now resize the DefView ListView window because ATL isn't very reliable at it.
  243. if (_hwndLV)
  244. {
  245. // During re-parenting of _hwndLV by Trident, the size of the OC is not known to Trident.
  246. // So, initially we get this message with 1 and 1 for the width and height, from it.
  247. // And once Trident knows it's correct dimensions, we again get this message with the proper dim.
  248. // We get a performance gain by not passing the first no-sense 1 x 1 dimension to _hwndLV.
  249. //
  250. if (m_rcPos.right - m_rcPos.left != 1 || m_rcPos.bottom - m_rcPos.top != 1)
  251. {
  252. ::SetWindowPos(_hwndLV, 0, 0, 0, m_rcPos.right - m_rcPos.left, m_rcPos.bottom - m_rcPos.top, SWP_NOZORDER);
  253. }
  254. }
  255. bHandled = FALSE;
  256. return 0;
  257. }
  258. HRESULT CWebViewFolderContents::DoVerbUIActivate(LPCRECT prcPosRect, HWND hwndParent)
  259. {
  260. HRESULT hr = IOleObjectImpl<CWebViewFolderContents>::DoVerbUIActivate(prcPosRect, hwndParent);
  261. if (SUCCEEDED(hr))
  262. {
  263. hr = _OnInPlaceActivate();
  264. }
  265. if (_hwndLV)
  266. {
  267. ::SetFocus(_hwndLV);
  268. }
  269. return hr;
  270. }
  271. // move from de-active to in-place-active
  272. HRESULT CWebViewFolderContents::_OnInPlaceActivate(void)
  273. {
  274. HRESULT hr = S_OK;
  275. if (_pdvf3 == NULL)
  276. {
  277. hr = IUnknown_QueryService(m_spClientSite, SID_DefView, IID_PPV_ARG(IDefViewFrame3, &_pdvf3));
  278. if (EVAL(SUCCEEDED(hr)))
  279. {
  280. HWND hwnd;
  281. hr = _pdvf3->GetWindowLV(&hwnd);
  282. if (SUCCEEDED(hr))
  283. {
  284. _ShowWindowLV(hwnd); // we got it -- show the listview
  285. }
  286. }
  287. }
  288. return hr;
  289. }
  290. HRESULT CWebViewFolderContents::DoVerbInPlaceActivate(LPCRECT prcPosRect, HWND hwndParent)
  291. {
  292. HRESULT hr = IOleObjectImpl<CWebViewFolderContents>::DoVerbInPlaceActivate(prcPosRect, hwndParent);
  293. if (EVAL(SUCCEEDED(hr)))
  294. {
  295. hr = _OnInPlaceActivate();
  296. }
  297. return hr;
  298. }
  299. HRESULT CWebViewFolderContents::InPlaceDeactivate(void)
  300. {
  301. _ReleaseWindow();
  302. ATOMICRELEASE(_pdvf3);
  303. return IOleInPlaceObject_InPlaceDeactivate();
  304. }
  305. HRESULT CWebViewFolderContents::SetObjectRects(LPCRECT prcPosRect, LPCRECT prcClipRect)
  306. {
  307. // WARNING: Do NOT move the EqualRect() comparison to after the
  308. // IOleInPlaceObject_SetObjectRects declaration. The EqualRect()
  309. // will always return an equal result then.
  310. bool bPositionRectDifferent = (EqualRect(&m_rcPos, prcPosRect) == 0);
  311. HRESULT hr = IOleInPlaceObject_SetObjectRects(prcPosRect, prcClipRect);
  312. // 99/02/23 #294278 vtan: Trident did not call this routine when
  313. // marquee selecting but it now does. The jumpy scrolling now
  314. // manifests. Check that posRect has not changed before making
  315. // any scroll position adjustments.
  316. if (_hwndLV && _pdvf3 && (!_fCalledOnSizeForThisSize || bPositionRectDifferent))
  317. {
  318. _pdvf3->OnResizeListView();
  319. _fCalledOnSizeForThisSize = TRUE;
  320. }
  321. return hr;
  322. }
  323. // IOleInPlaceActiveObject
  324. HRESULT CWebViewFolderContents::TranslateAccelerator(MSG *pMsg)
  325. {
  326. HRESULT hr = S_OK;
  327. if (!_fTabRecieved)
  328. {
  329. hr = IOleInPlaceActiveObjectImpl<CWebViewFolderContents>::TranslateAccelerator(pMsg);
  330. // If we did not handle this and if it is a tab (and we are not getting it in a cycle), forward it to trident, if present.
  331. if (hr != S_OK && pMsg && (pMsg->wParam == VK_TAB || pMsg->wParam == VK_F6) && m_spClientSite)
  332. {
  333. IOleControlSite* pocs;
  334. if (SUCCEEDED(m_spClientSite->QueryInterface(IID_PPV_ARG(IOleControlSite, &pocs))))
  335. {
  336. DWORD grfModifiers = 0;
  337. if (GetKeyState(VK_SHIFT) & 0x8000)
  338. {
  339. grfModifiers |= 0x1; //KEYMOD_SHIFT
  340. }
  341. if (GetKeyState(VK_CONTROL) & 0x8000)
  342. {
  343. grfModifiers |= 0x2; //KEYMOD_CONTROL;
  344. }
  345. if (GetKeyState(VK_MENU) & 0x8000)
  346. {
  347. grfModifiers |= 0x4; //KEYMOD_ALT;
  348. }
  349. _fTabRecieved = TRUE;
  350. hr = pocs->TranslateAccelerator(pMsg, grfModifiers);
  351. _fTabRecieved = FALSE;
  352. pocs->Release();
  353. }
  354. }
  355. }
  356. return hr;
  357. }
  358. // IProvideClassInfo
  359. HRESULT CWebViewFolderContents::GetClassInfo(ITypeInfo ** ppTI)
  360. {
  361. if (!_pClassTypeInfo)
  362. GetTypeInfoFromLibId(LANGIDFROMLCID(g_lcidLocaleUnicpp), LIBID_Shell32, 1, 0,
  363. CLSID_WebViewFolderContents, &_pClassTypeInfo);
  364. if (EVAL(_pClassTypeInfo))
  365. {
  366. _pClassTypeInfo->AddRef();
  367. *ppTI = _pClassTypeInfo;
  368. return S_OK;
  369. }
  370. *ppTI = NULL;
  371. return E_FAIL;
  372. }
  373. HRESULT CWebViewFolderContents::GetTypeInfo(UINT itinfo, LCID lcid, ITypeInfo** ppITypeInfo)
  374. {
  375. HRESULT hr = S_OK;
  376. *ppITypeInfo = NULL;
  377. if (0 != itinfo)
  378. return TYPE_E_ELEMENTNOTFOUND;
  379. //Load a type lib if we don't have the information already.
  380. if (NULL == *ppITypeInfo)
  381. {
  382. ITypeInfo * pITIDisp;
  383. hr = GetTypeInfoFromLibId(lcid, LIBID_Shell32, 1, 0,
  384. IID_IShellFolderViewDual2, &pITIDisp);
  385. if (SUCCEEDED(hr))
  386. {
  387. HREFTYPE hrefType;
  388. // All our IDispatch implementations are DUAL. GetTypeInfoOfGuid
  389. // returns the ITypeInfo of the IDispatch-part only. We need to
  390. // find the ITypeInfo for the dual interface-part.
  391. //
  392. HRESULT hrT = pITIDisp->GetRefTypeOfImplType(0xffffffff, &hrefType);
  393. if (SUCCEEDED(hrT))
  394. hrT = pITIDisp->GetRefTypeInfo(hrefType, ppITypeInfo);
  395. ASSERT(SUCCEEDED(hrT));
  396. pITIDisp->Release();
  397. }
  398. }
  399. return hr;
  400. }
  401. HRESULT CWebViewFolderContents::GetIDsOfNames(REFIID /*riid*/, LPOLESTR* rgszNames,
  402. UINT cNames, LCID lcid, DISPID* rgdispid)
  403. {
  404. ITypeInfo* pInfo;
  405. HRESULT hr = GetTypeInfo(0, lcid, &pInfo);
  406. if (pInfo != NULL)
  407. {
  408. hr = pInfo->GetIDsOfNames(rgszNames, cNames, rgdispid);
  409. pInfo->Release();
  410. }
  411. TraceMsg(TF_DEFVIEW, "CWebViewFolderContents::GetIDsOfNames(DISPID=%ls, lcid=%d, cNames=%d) returned hr=%#08lx", *rgszNames, lcid, cNames, hr);
  412. return hr;
  413. }
  414. HRESULT CWebViewFolderContents::Invoke(DISPID dispidMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS * pdispparams, VARIANT * pvarResult, EXCEPINFO * pexcepinfo, UINT * puArgErr)
  415. {
  416. HRESULT hr = E_FAIL;
  417. DISPPARAMS dispparams = {0};
  418. if (!pdispparams)
  419. pdispparams = &dispparams; // otherwise OLE Fails when passed NULL.
  420. if (dispidMember == DISPID_WINDOWOBJECT)
  421. {
  422. IDispatch * pdisp;
  423. if (SUCCEEDED(get_Script(&pdisp)))
  424. {
  425. hr = pdisp->Invoke(dispidMember, riid, lcid, wFlags, pdispparams, pvarResult, pexcepinfo, puArgErr);
  426. pdisp->Release();
  427. return hr;
  428. }
  429. else
  430. return DISP_E_MEMBERNOTFOUND;
  431. }
  432. // Make sure we are connected up to defviews automation.
  433. hr = _SetupAutomationForwarders();
  434. if (SUCCEEDED(hr))
  435. hr = _pdispAuto->Invoke(dispidMember, riid, lcid, wFlags, pdispparams, pvarResult, pexcepinfo, puArgErr);
  436. return hr;
  437. }
  438. #define DW_MISC_STATUS (OLEMISC_SETCLIENTSITEFIRST | OLEMISC_ACTIVATEWHENVISIBLE | OLEMISC_CANTLINKINSIDE | OLEMISC_INSIDEOUT)
  439. HRESULT CWebViewFolderContents::GetMiscStatus(DWORD dwAspect, DWORD *pdwStatus)
  440. {
  441. *pdwStatus = DW_MISC_STATUS;
  442. return S_OK;
  443. }
  444. void CWebViewFolderContents::_ShowWindowLV(HWND hwndLV)
  445. {
  446. if (!hwndLV)
  447. return;
  448. _hwndLV = hwndLV;
  449. _hwndLVParent = ::GetParent(_hwndLV);
  450. SHSetParentHwnd(_hwndLV, m_hWnd);
  451. LONG lExStyle = ::GetWindowLong(_hwndLV, GWL_EXSTYLE);
  452. _fClientEdge = lExStyle & WS_EX_CLIENTEDGE ? TRUE : FALSE;
  453. UINT uFlags = SWP_NOZORDER;
  454. if (_fClientEdge)
  455. {
  456. lExStyle &= ~WS_EX_CLIENTEDGE;
  457. ::SetWindowLong(_hwndLV, GWL_EXSTYLE, lExStyle);
  458. uFlags |= SWP_FRAMECHANGED;
  459. }
  460. ::SetWindowPos(_hwndLV, 0, 0, 0, m_rcPos.right - m_rcPos.left
  461. , m_rcPos.bottom - m_rcPos.top, uFlags);
  462. _pdvf3->ShowHideListView();
  463. }
  464. void CWebViewFolderContents::_ReleaseWindow()
  465. {
  466. if (_hwndLV)
  467. {
  468. UINT uFlags = SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE;
  469. if (_fClientEdge)
  470. {
  471. SetWindowBits(_hwndLV, GWL_EXSTYLE, WS_EX_CLIENTEDGE, WS_EX_CLIENTEDGE);
  472. uFlags |= SWP_FRAMECHANGED;
  473. }
  474. SHSetParentHwnd(_hwndLV, _hwndLVParent);
  475. ::SetWindowPos(_hwndLV, HWND_BOTTOM, 0, 0, 0, 0, uFlags);
  476. _pdvf3->ReleaseWindowLV();
  477. _hwndLV = NULL;
  478. }
  479. }
  480. // IConnectionPointContainer
  481. HRESULT CWebViewFolderContents::EnumConnectionPoints(IEnumConnectionPoints **ppEnum)
  482. {
  483. HRESULT hr = _SetupAutomationForwarders();
  484. if (SUCCEEDED(hr))
  485. hr = CreateInstance_IEnumConnectionPoints(ppEnum, 1, SAFECAST(&m_cpEvents, IConnectionPoint*));
  486. return hr;
  487. }
  488. HRESULT CWebViewFolderContents::FindConnectionPoint(REFIID iid, IConnectionPoint **ppCP)
  489. {
  490. *ppCP = NULL;
  491. HRESULT hr = _SetupAutomationForwarders();
  492. if (SUCCEEDED(hr))
  493. {
  494. if (IsEqualIID(iid, DIID_DShellFolderViewEvents) || IsEqualIID(iid, IID_IDispatch))
  495. {
  496. *ppCP = SAFECAST(&m_cpEvents, IConnectionPoint*);
  497. (*ppCP)->AddRef();
  498. hr = S_OK;
  499. }
  500. else
  501. {
  502. hr = E_NOINTERFACE;
  503. }
  504. }
  505. return hr;
  506. }
  507. // IConnectionPoint
  508. //
  509. // Our IConnectionPoint is really implemented by defview's CFolder's connection point.
  510. // We just need to keep a count of outstanding references so we can force Unadvise
  511. // calls during "implicit unadvise during shutdown" cases like Trident.
  512. // (Is this really the spec? It doesn't sound very robust...)
  513. //
  514. HRESULT CWebViewFolderContents::CConnectionPointForwarder::QueryInterface(REFIID riid, void **ppvObj)
  515. {
  516. static const QITAB qit[] = {
  517. QITABENT(CConnectionPointForwarder, IConnectionPoint), // IID_IConnectionPoint
  518. { 0 }
  519. };
  520. return QISearch(this, qit, riid, ppvObj);
  521. }
  522. STDMETHODIMP_(ULONG) CWebViewFolderContents::CConnectionPointForwarder::AddRef(void)
  523. {
  524. return _punkParent->AddRef();
  525. }
  526. STDMETHODIMP_(ULONG) CWebViewFolderContents::CConnectionPointForwarder::Release(void)
  527. {
  528. return _punkParent->Release();
  529. }
  530. HRESULT CWebViewFolderContents::CConnectionPointForwarder::GetConnectionInterface(IID * pIID)
  531. {
  532. HRESULT hr = _pcpAuto->GetConnectionInterface(pIID);
  533. if (SUCCEEDED(hr))
  534. {
  535. ASSERT(IsEqualIID(*pIID, DIID_DShellFolderViewEvents));
  536. }
  537. return hr;
  538. }
  539. HRESULT CWebViewFolderContents::CConnectionPointForwarder::GetConnectionPointContainer(IConnectionPointContainer ** ppCPC)
  540. {
  541. return _punkParent->QueryInterface(IID_PPV_ARG(IConnectionPointContainer, ppCPC));
  542. }
  543. HRESULT CWebViewFolderContents::CConnectionPointForwarder::Advise(IUnknown * pUnkSink, DWORD * pdwCookie)
  544. {
  545. if (!_dsaCookies)
  546. {
  547. _dsaCookies = DSA_Create(sizeof(*pdwCookie), 4);
  548. if (!_dsaCookies)
  549. {
  550. *pdwCookie = 0;
  551. return E_OUTOFMEMORY;
  552. }
  553. }
  554. HRESULT hr = _pcpAuto->Advise(pUnkSink, pdwCookie);
  555. if (SUCCEEDED(hr))
  556. {
  557. if (-1 == DSA_AppendItem(_dsaCookies, pdwCookie))
  558. {
  559. _pcpAuto->Unadvise(*pdwCookie);
  560. *pdwCookie = 0;
  561. hr = E_OUTOFMEMORY;
  562. }
  563. }
  564. return hr;
  565. }
  566. HRESULT CWebViewFolderContents::CConnectionPointForwarder::Unadvise(DWORD dwCookie)
  567. {
  568. if (_dsaCookies)
  569. {
  570. int i = 0;
  571. DWORD dw;
  572. while (DSA_GetItem(_dsaCookies, i++, &dw))
  573. {
  574. if (dw == dwCookie)
  575. {
  576. DSA_DeleteItem(_dsaCookies, --i);
  577. return _pcpAuto->Unadvise(dwCookie);
  578. }
  579. }
  580. }
  581. return E_FAIL;
  582. }
  583. void CWebViewFolderContents::_UnadviseAll()
  584. {
  585. if (m_cpEvents._dsaCookies)
  586. {
  587. if (m_cpEvents._pcpAuto)
  588. {
  589. DWORD dw;
  590. for (int i = 0; DSA_GetItem(m_cpEvents._dsaCookies, i, &dw); i++)
  591. {
  592. m_cpEvents._pcpAuto->Unadvise(dw);
  593. }
  594. }
  595. DSA_Destroy(m_cpEvents._dsaCookies);
  596. m_cpEvents._dsaCookies = NULL;
  597. }
  598. }
  599. HRESULT CWebViewFolderContents::Close(DWORD dwSaveOption)
  600. {
  601. _UnadviseAll();
  602. HRESULT hr = IOleObjectImpl<CWebViewFolderContents>::Close(dwSaveOption);
  603. _ReleaseAutomationForwarders();
  604. return hr;
  605. }
  606. HRESULT CWebViewFolderContents::_SetupAutomationForwarders(void)
  607. {
  608. HRESULT hr = S_OK;
  609. if (!m_cpEvents._pcpAuto)
  610. {
  611. IShellView *psv;
  612. hr = IUnknown_QueryService(m_spClientSite, SID_DefView, IID_PPV_ARG(IShellView, &psv));
  613. if (SUCCEEDED(hr))
  614. {
  615. IDispatch *pdisp;
  616. hr = psv->GetItemObject(SVGIO_BACKGROUND, IID_PPV_ARG(IDispatch, &pdisp));
  617. if (SUCCEEDED(hr))
  618. {
  619. hr = pdisp->QueryInterface(IID_PPV_ARG(IShellFolderViewDual2, &_pdispAuto));
  620. if (SUCCEEDED(hr))
  621. {
  622. if (SUCCEEDED(MakeSafeForScripting((IUnknown**)&_pdispAuto)))
  623. {
  624. IUnknown_SetSite(_pdispAuto, m_spClientSite);
  625. // Need to get the right interfaces
  626. IConnectionPointContainer* pcpcAuto;
  627. hr = _pdispAuto->QueryInterface(IID_PPV_ARG(IConnectionPointContainer, &pcpcAuto));
  628. if (SUCCEEDED(hr))
  629. {
  630. hr = pcpcAuto->FindConnectionPoint(IID_IDispatch, &m_cpEvents._pcpAuto);
  631. pcpcAuto->Release();
  632. }
  633. if (FAILED(hr))
  634. {
  635. IUnknown_SetSite(_pdispAuto, NULL);
  636. ATOMICRELEASE(_pdispAuto);
  637. }
  638. }
  639. }
  640. pdisp->Release();
  641. }
  642. psv->Release();
  643. }
  644. }
  645. return hr;
  646. }
  647. HRESULT CWebViewFolderContents::_ReleaseAutomationForwarders(void)
  648. {
  649. ATOMICRELEASE(m_cpEvents._pcpAuto);
  650. IUnknown_SetSite(_pdispAuto, NULL);
  651. ATOMICRELEASE(_pdispAuto);
  652. return S_OK;
  653. }
  654. // IShellFolderViewDual2
  655. // We will let the folder object get created and have it maintain that we only have one
  656. // application object (with the site) set properly...
  657. HRESULT CWebViewFolderContents::get_Application(IDispatch **ppid)
  658. {
  659. *ppid = NULL;
  660. HRESULT hr = _SetupAutomationForwarders();
  661. if (SUCCEEDED(hr))
  662. hr = _pdispAuto->get_Application(ppid);
  663. return hr;
  664. }
  665. HRESULT CWebViewFolderContents::get_Parent(IDispatch **ppid)
  666. {
  667. *ppid = NULL;
  668. HRESULT hr = _SetupAutomationForwarders();
  669. if (SUCCEEDED(hr))
  670. hr = _pdispAuto->get_Parent(ppid);
  671. return hr;
  672. }
  673. HRESULT CWebViewFolderContents::get_Folder(Folder **ppid)
  674. {
  675. *ppid = NULL;
  676. HRESULT hr = _SetupAutomationForwarders();
  677. if (SUCCEEDED(hr))
  678. hr = _pdispAuto->get_Folder(ppid);
  679. return hr;
  680. }
  681. HRESULT CWebViewFolderContents::SelectedItems(FolderItems **ppid)
  682. {
  683. // We need to talk to the actual window under us
  684. *ppid = NULL;
  685. HRESULT hr = _SetupAutomationForwarders();
  686. if (SUCCEEDED(hr))
  687. hr = _pdispAuto->SelectedItems(ppid);
  688. return hr;
  689. }
  690. HRESULT CWebViewFolderContents::get_FocusedItem(FolderItem **ppid)
  691. {
  692. *ppid = NULL;
  693. HRESULT hr = _SetupAutomationForwarders();
  694. if (SUCCEEDED(hr))
  695. hr = _pdispAuto->get_FocusedItem(ppid);
  696. return hr;
  697. }
  698. HRESULT CWebViewFolderContents::SelectItem(VARIANT *pvfi, int dwFlags)
  699. {
  700. HRESULT hr = _SetupAutomationForwarders();
  701. if (SUCCEEDED(hr))
  702. hr = _pdispAuto->SelectItem(pvfi, dwFlags);
  703. return hr;
  704. }
  705. HRESULT CWebViewFolderContents::PopupItemMenu(FolderItem *pfi, VARIANT vx, VARIANT vy, BSTR * pbs)
  706. {
  707. HRESULT hr = _SetupAutomationForwarders();
  708. if (SUCCEEDED(hr))
  709. hr = _pdispAuto->PopupItemMenu(pfi, vx, vy, pbs);
  710. return hr;
  711. }
  712. HRESULT CWebViewFolderContents::get_Script(IDispatch **ppid)
  713. {
  714. *ppid = NULL;
  715. HRESULT hr = _SetupAutomationForwarders();
  716. if (SUCCEEDED(hr))
  717. hr = _pdispAuto->get_Script(ppid);
  718. return hr;
  719. }
  720. HRESULT CWebViewFolderContents::get_ViewOptions(long *plSetting)
  721. {
  722. HRESULT hr = _SetupAutomationForwarders();
  723. if (SUCCEEDED(hr))
  724. hr = _pdispAuto->get_ViewOptions(plSetting);
  725. return hr;
  726. }
  727. HRESULT CWebViewFolderContents::get_CurrentViewMode(UINT *pViewMode)
  728. {
  729. HRESULT hr = _SetupAutomationForwarders();
  730. if (SUCCEEDED(hr))
  731. hr = _pdispAuto->get_CurrentViewMode(pViewMode);
  732. return hr;
  733. }
  734. HRESULT CWebViewFolderContents::put_CurrentViewMode(UINT ViewMode)
  735. {
  736. HRESULT hr = _SetupAutomationForwarders();
  737. if (SUCCEEDED(hr))
  738. hr = _pdispAuto->put_CurrentViewMode(ViewMode);
  739. return hr;
  740. }
  741. HRESULT CWebViewFolderContents::SelectItemRelative(int iRelative)
  742. {
  743. HRESULT hr = _SetupAutomationForwarders();
  744. if (SUCCEEDED(hr))
  745. hr = _pdispAuto->SelectItemRelative(iRelative);
  746. return hr;
  747. }
  748. HRESULT CWebViewFolderContents::QueryService(REFGUID guidService, REFIID riid, void **ppv)
  749. {
  750. return IUnknown_QueryService(m_spClientSite, SID_DefView, riid, ppv);
  751. }
  752. STDAPI CWebViewFolderContents_CreateInstance(IUnknown *punkOuter, REFIID riid, void **ppvOut)
  753. {
  754. return CComCreator< CComPolyObject< CWebViewFolderContents > >::CreateInstance((void *) punkOuter, riid, ppvOut);
  755. }