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.

567 lines
16 KiB

  1. #include "precomp.h"
  2. #include <shimgvw.h>
  3. #include "PrevCtrl.h"
  4. #include "autosecurity.h"
  5. #include <dispex.h>
  6. #pragma hdrstop
  7. LRESULT CPreview::OnCreate(UINT , WPARAM , LPARAM , BOOL&)
  8. {
  9. ATLTRACE(_T("CPreview::OnCreate\n"));
  10. // Create the preview window
  11. RECT rcWnd;
  12. GetClientRect(&rcWnd);
  13. if (m_cwndPreview.Create(m_hWnd, rcWnd, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, 0))
  14. {
  15. m_cwndPreview.SetNotify(this);
  16. HPALETTE hpal;
  17. if (SUCCEEDED(GetAmbientPalette(hpal)))
  18. m_cwndPreview.SetPalette(hpal);
  19. return 0;
  20. }
  21. return -1;
  22. }
  23. LRESULT CPreview::OnActivate(UINT , WPARAM , LPARAM , BOOL& bHandled)
  24. {
  25. ATLTRACE(_T("CPreview::OnActivate\n"));
  26. m_cwndPreview.SetFocus();
  27. bHandled = false;
  28. return 0;
  29. }
  30. HRESULT CPreview::OnDrawAdvanced(ATL_DRAWINFO&)
  31. {
  32. ATLTRACE(_T("CPreview::OnDrawAdvanced\n"));
  33. return S_OK;
  34. }
  35. LRESULT CPreview::OnEraseBkgnd(UINT , WPARAM , LPARAM , BOOL&)
  36. {
  37. ATLTRACE(_T("CPreview::OnEraseBkgnd\n"));
  38. return TRUE;
  39. }
  40. LRESULT CPreview::OnSize(UINT , WPARAM , LPARAM lParam, BOOL&)
  41. {
  42. ATLTRACE(_T("CPreview::OnSize\n"));
  43. ::SetWindowPos(m_cwndPreview.m_hWnd, NULL, 0,0,
  44. LOWORD(lParam), HIWORD(lParam), SWP_NOZORDER | SWP_NOACTIVATE);
  45. return 0;
  46. }
  47. // IObjectSafety::GetInterfaceSafetyOptions
  48. //
  49. // This method never gets called. We are safe for any and every thing. There should
  50. // be no possible way that this control could lose, destroy, or expose data.
  51. STDMETHODIMP CPreview::GetInterfaceSafetyOptions(REFIID riid, DWORD *pdwSupportedOptions,
  52. DWORD *pdwEnabledOptions)
  53. {
  54. ATLTRACE(_T("IObjectSafetyImpl::GetInterfaceSafetyOptions\n"));
  55. HRESULT hr;
  56. hr = IObjectSafetyImpl<CPreview, INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA>::GetInterfaceSafetyOptions(riid, pdwSupportedOptions, pdwEnabledOptions);
  57. if (SUCCEEDED(hr))
  58. {
  59. IsHostLocalZone(CAS_REG_VALIDATION, &hr);
  60. }
  61. return hr;
  62. }
  63. STDMETHODIMP CPreview::SetInterfaceSafetyOptions(REFIID riid, DWORD dwSupportedOptions,
  64. DWORD dwEnabledOptions)
  65. {
  66. ATLTRACE(_T("IObjectSafetyImpl::SetInterfaceSafetyOptions\n"));
  67. HRESULT hr;
  68. hr = IObjectSafetyImpl<CPreview, INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA>::SetInterfaceSafetyOptions(riid, dwSupportedOptions, dwEnabledOptions);
  69. if (SUCCEEDED(hr))
  70. {
  71. IsHostLocalZone(CAS_REG_VALIDATION, &hr);
  72. }
  73. return hr;
  74. }
  75. // IPersistPropertyBag::Load
  76. //
  77. // We have the following properties that we can load from the property bag:
  78. // Toolbar false/zero = don't show the toolbar, otherwise show the toolbar
  79. // Full Screen false/zero = don't show fullscreen button on toolbar, otherwise show the button
  80. // Context Menu false/zero = don't show context menu, otherwise show the context menu when the user right clicks
  81. // Print Button false/zero = don't show print button on toolbar, otherwise show the button
  82. STDMETHODIMP CPreview::Load(IPropertyBag * pPropBag, IErrorLog * pErrorLog)
  83. {
  84. HRESULT hr;
  85. VARIANT var;
  86. BOOL bDummy = TRUE;
  87. var.vt = VT_UI4;
  88. var.ulVal = TRUE;
  89. hr = pPropBag->Read(L"Toolbar", &var, NULL);
  90. if (SUCCEEDED(hr) && var.vt==VT_UI4)
  91. {
  92. m_cwndPreview.IV_OnSetOptions(IV_SETOPTIONS,IVO_TOOLBAR,var.ulVal,bDummy);
  93. }
  94. var.vt = VT_UI4;
  95. var.ulVal = TRUE;
  96. hr = pPropBag->Read(L"Full Screen", &var, NULL);
  97. if (SUCCEEDED(hr) && var.vt==VT_UI4)
  98. {
  99. m_cwndPreview.IV_OnSetOptions(IV_SETOPTIONS,IVO_FULLSCREENBTN,var.ulVal,bDummy);
  100. }
  101. var.vt = VT_UI4;
  102. var.ulVal = TRUE;
  103. hr = pPropBag->Read(L"Print Button", &var, NULL);
  104. if (SUCCEEDED(hr) && var.vt==VT_UI4)
  105. {
  106. m_cwndPreview.IV_OnSetOptions(IV_SETOPTIONS,IVO_PRINTBTN,var.ulVal,bDummy);
  107. }
  108. var.vt = VT_UI4;
  109. var.ulVal = TRUE;
  110. hr = pPropBag->Read(L"Context Menu", &var, NULL);
  111. if (SUCCEEDED(hr) && var.vt==VT_UI4)
  112. {
  113. m_cwndPreview.IV_OnSetOptions(IV_SETOPTIONS,IVO_CONTEXTMENU,var.ulVal,bDummy);
  114. }
  115. var.vt = VT_UI4;
  116. var.ulVal = FALSE;
  117. hr = pPropBag->Read(L"Allow Online", &var, NULL);
  118. if (SUCCEEDED(hr) && var.vt==VT_UI4)
  119. {
  120. m_cwndPreview.IV_OnSetOptions(IV_SETOPTIONS,IVO_ALLOWGOONLINE,var.ulVal,bDummy);
  121. }
  122. var.vt = VT_UI4;
  123. var.ulVal = FALSE;
  124. hr = pPropBag->Read(L"Disable Edit", &var, NULL);
  125. if (SUCCEEDED(hr) && var.vt==VT_UI4)
  126. {
  127. m_cwndPreview.IV_OnSetOptions(IV_SETOPTIONS,IVO_DISABLEEDIT,var.ulVal,bDummy);
  128. }
  129. return S_OK;
  130. }
  131. // If we are initialized via IStream, read a DWORD from the stream that is a mask
  132. // for which toolbar buttons to show
  133. STDMETHODIMP CPreview::Load(IStream *pStream)
  134. {
  135. DWORD dwFlags = 0;
  136. ULONG ulRead = 0;
  137. BOOL bDummy = TRUE;
  138. if (SUCCEEDED(pStream->Read(&dwFlags, sizeof(dwFlags), &ulRead)) && ulRead == sizeof(dwFlags))
  139. {
  140. m_cwndPreview.IV_OnSetOptions(IV_SETOPTIONS,IVO_TOOLBAR,dwFlags & PVTB_TOOLBAR, bDummy);
  141. m_cwndPreview.IV_OnSetOptions(IV_SETOPTIONS,IVO_FULLSCREENBTN,dwFlags & PVTB_HIDEFULLSCREEN, bDummy);
  142. m_cwndPreview.IV_OnSetOptions(IV_SETOPTIONS,IVO_PRINTBTN,dwFlags & PVTB_HIDEPRINTBTN, bDummy);
  143. m_cwndPreview.IV_OnSetOptions(IV_SETOPTIONS,IVO_CONTEXTMENU,dwFlags & PVTB_CONTEXTMENU, bDummy);
  144. m_cwndPreview.IV_OnSetOptions(IV_SETOPTIONS,IVO_ALLOWGOONLINE,dwFlags & PVTB_ALLOWONLINE, bDummy);
  145. m_cwndPreview.IV_OnSetOptions(IV_SETOPTIONS,IVO_DISABLEEDIT,dwFlags & PVTB_DISABLEEDIT, bDummy);
  146. }
  147. return S_OK;
  148. }
  149. // IPreview Methods:
  150. STDMETHODIMP CPreview::ShowFile(BSTR bstrFileName)
  151. {
  152. m_cwndPreview.ShowFile(bstrFileName, 1);
  153. return S_OK;
  154. }
  155. STDMETHODIMP CPreview::ShowFile(BSTR bstrFileName, int iSelectCount)
  156. {
  157. m_cwndPreview.ShowFile(bstrFileName, iSelectCount);
  158. return S_OK;
  159. }
  160. STDMETHODIMP CPreview::Show(VARIANT var)
  161. {
  162. HRESULT hr;
  163. switch (var.vt)
  164. {
  165. case VT_UNKNOWN:
  166. case VT_DISPATCH:
  167. // QI for Folder Item
  168. if (var.punkVal)
  169. {
  170. FolderItems *pfis;
  171. FolderItem *pfi;
  172. hr = var.punkVal->QueryInterface(IID_PPV_ARG(FolderItem, &pfi));
  173. if (SUCCEEDED(hr))
  174. {
  175. // If the item is a link we want to get the link's target:
  176. VARIANT_BOOL vbool;
  177. hr = pfi->get_IsLink(&vbool);
  178. if (SUCCEEDED(hr) && (VARIANT_FALSE != vbool)) // IsLink returns TRUE, not VARIANT_TRUE
  179. {
  180. IDispatch *pdisp;
  181. hr = pfi->get_GetLink(&pdisp);
  182. if (SUCCEEDED(hr) && pdisp)
  183. {
  184. IShellLinkDual2 * psl2;
  185. hr = pdisp->QueryInterface(IID_PPV_ARG(IShellLinkDual2, &psl2));
  186. if (SUCCEEDED(hr) && psl2)
  187. {
  188. FolderItem * pfiTarg;
  189. hr = psl2->get_Target(&pfiTarg);
  190. if (SUCCEEDED(hr) && pfiTarg)
  191. {
  192. pfi->Release();
  193. pfi = pfiTarg;
  194. }
  195. psl2->Release();
  196. }
  197. pdisp->Release();
  198. }
  199. }
  200. // Now we need to know the path for this item. We can only view items if
  201. // we can get a path or URL to the target so some namespaces aren't viewable.
  202. BSTR bstr;
  203. hr = pfi->get_Path(&bstr);
  204. if (SUCCEEDED(hr))
  205. {
  206. m_cwndPreview.ShowFile(bstr, 1);
  207. SysFreeString(bstr);
  208. hr = S_OK;
  209. }
  210. else
  211. {
  212. // we couldn't get the path so we will display the "No Preview" message
  213. m_cwndPreview.ShowFile(NULL, 1);
  214. hr = S_FALSE;
  215. }
  216. // now release the Folder Item pointer
  217. pfi->Release();
  218. return hr;
  219. }
  220. else if (SUCCEEDED(var.punkVal->QueryInterface(IID_PPV_ARG(FolderItems, &pfis))))
  221. {
  222. // currently in the multi-select case we just show the multi-select message.
  223. // eventually this should go to slideshow mode
  224. m_cwndPreview.ShowFile(NULL, 2);
  225. pfis->Release();
  226. return S_FALSE;
  227. }
  228. }
  229. // the unknown pointer isn't for an object type that we know about
  230. return E_INVALIDARG;
  231. case VT_BSTR:
  232. m_cwndPreview.ShowFile(var.bstrVal, 1);
  233. break;
  234. case VT_BOOL:
  235. // show(false) will hide the currently previewed item
  236. if (VARIANT_FALSE == var.boolVal)
  237. {
  238. m_cwndPreview.ShowFile(NULL, 0);
  239. return S_OK;
  240. }
  241. else
  242. {
  243. return E_INVALIDARG;
  244. }
  245. default:
  246. return E_INVALIDARG;
  247. }
  248. return S_OK;
  249. }
  250. //*** IsVK_TABCycler -- is key a TAB-equivalent
  251. // ENTRY/EXIT
  252. // dir 0 if not a TAB, non-0 if a TAB
  253. // NOTES
  254. // NYI: -1 for shift+tab, 1 for tab
  255. // cloned from browseui/util.cpp
  256. //
  257. int IsVK_TABCycler(MSG *pMsg)
  258. {
  259. if (!pMsg)
  260. return 0;
  261. if (pMsg->message != WM_KEYDOWN)
  262. return 0;
  263. if (! (pMsg->wParam == VK_TAB || pMsg->wParam == VK_F6))
  264. return 0;
  265. #if 0 // todo?
  266. return (GetAsyncKeyState(VK_SHIFT) < 0) ? -1 : 1;
  267. #endif
  268. return 1;
  269. }
  270. //***
  271. // NOTES
  272. // hard-coded 1/2/4 (vs. KEYMOD_*) is same thing atlctl.h does. go figure...
  273. DWORD GetGrfMods()
  274. {
  275. DWORD dwMods;
  276. dwMods = 0;
  277. if (GetAsyncKeyState(VK_SHIFT) < 0)
  278. dwMods |= 1; // KEYMOD_SHIFT
  279. if (GetAsyncKeyState(VK_CONTROL) < 0)
  280. dwMods |= 2; // KEYMOD_CONTROL
  281. if (GetAsyncKeyState(VK_MENU) < 0)
  282. dwMods |= 4; // KEYMOD_MENU
  283. return dwMods;
  284. }
  285. STDMETHODIMP CPreview::TranslateAccelerator(LPMSG lpmsg)
  286. {
  287. ATLTRACE(_T("CPreview::TranslateAccelerator\n"));
  288. if (m_cwndPreview.TranslateAccelerator(lpmsg))
  289. {
  290. return S_OK;
  291. }
  292. if (IsVK_TABCycler(lpmsg))
  293. {
  294. // REVIEW: looks like newer versions of ATL might do this for us so
  295. // possibly we can replace w/ call to SUPER::TA when we upgrade.
  296. CComQIPtr <IOleControlSite, &IID_IOleControlSite> spOCS(m_spClientSite);
  297. if (spOCS) {
  298. return spOCS->TranslateAccelerator(lpmsg, GetGrfMods());
  299. }
  300. }
  301. return S_FALSE;
  302. }
  303. STDMETHODIMP CPreview::OnFrameWindowActivate(BOOL fActive)
  304. {
  305. if (fActive)
  306. {
  307. m_cwndPreview.SetFocus();
  308. }
  309. return S_OK;
  310. }
  311. LRESULT CPreview::OnSetFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  312. {
  313. ATLTRACE(_T("CPreview::OnSetFocus\n"));
  314. LRESULT ret = CComControl<CPreview>::OnSetFocus(uMsg,wParam,lParam, bHandled);
  315. m_cwndPreview.SetFocus();
  316. return ret;
  317. }
  318. STDMETHODIMP CPreview::get_printable(BOOL * pVal)
  319. {
  320. // If we don't trust the host, we tell them it is always printable because we don't
  321. // want them to be able to see if the file exists on the disk. Hackers can use
  322. // this to determine where the OS is installed and which apps are installed.
  323. *pVal = TRUE;
  324. if (IsHostLocalZone(CAS_REG_VALIDATION, NULL))
  325. {
  326. *pVal = m_cwndPreview.GetPrintable();
  327. }
  328. return S_OK;
  329. }
  330. STDMETHODIMP CPreview::put_printable(BOOL newVal)
  331. {
  332. return S_FALSE;
  333. }
  334. STDMETHODIMP CPreview::get_cxImage(long * pVal)
  335. {
  336. // REVIEW: Return an error and set output to zero if no image is currently displayed?
  337. *pVal = m_cwndPreview.m_ctlPreview.m_cxImage;
  338. return S_OK;
  339. }
  340. STDMETHODIMP CPreview::get_cyImage(long * pVal)
  341. {
  342. // REVIEW: Return an error and set output to zero if no image is currently displayed?
  343. *pVal = m_cwndPreview.m_ctlPreview.m_cyImage;
  344. return S_OK;
  345. }
  346. STDMETHODIMP CPreview::Zoom(int iDirection)
  347. {
  348. switch (iDirection)
  349. {
  350. case -1:
  351. m_cwndPreview.ZoomOut();
  352. break;
  353. case 0:
  354. return S_OK;
  355. case 1:
  356. m_cwndPreview.ZoomIn();
  357. break;
  358. default:
  359. return S_FALSE;
  360. }
  361. return S_OK;
  362. }
  363. STDMETHODIMP CPreview::BestFit()
  364. {
  365. m_cwndPreview.BestFit();
  366. return S_OK;
  367. }
  368. STDMETHODIMP CPreview::ActualSize()
  369. {
  370. m_cwndPreview.ActualSize();
  371. return S_OK;
  372. }
  373. STDMETHODIMP CPreview::SlideShow()
  374. {
  375. HRESULT hr = m_cwndPreview.StartSlideShow(NULL);
  376. return SUCCEEDED(hr) ? S_OK : S_FALSE;
  377. }
  378. STDMETHODIMP CPreview::Rotate(DWORD dwAngle)
  379. {
  380. HRESULT hr = m_cwndPreview.Rotate(dwAngle);
  381. return SUCCEEDED(hr) ? S_OK : S_FALSE;
  382. }
  383. STDMETHODIMP CPreview::SetClientSite(IOleClientSite *pClientSite)
  384. {
  385. IOleObjectImpl<CPreview>::SetClientSite(pClientSite);
  386. m_cwndPreview.SetSite(pClientSite);
  387. return S_OK;
  388. }
  389. STDMETHODIMP CPreview::SetSite(IUnknown* punkSite)
  390. {
  391. IObjectWithSiteImpl<CPreview>::SetSite(punkSite);
  392. m_cwndPreview.SetSite(punkSite);
  393. if (punkSite)
  394. {
  395. if (!_pfv)
  396. {
  397. IShellView *psv;
  398. if (SUCCEEDED(IUnknown_QueryService(punkSite, SID_DefView, IID_PPV_ARG(IShellView, &psv))))
  399. {
  400. IDispatch *pdisp;
  401. if (SUCCEEDED(psv->GetItemObject(SVGIO_BACKGROUND, IID_PPV_ARG(IDispatch, &pdisp))))
  402. {
  403. ConnectToConnectionPoint(SAFECAST(this, IPreview2 *), DIID_DShellFolderViewEvents, TRUE, pdisp, &_dwConnectionCookie, NULL);
  404. _ProcessSelection();
  405. pdisp->Release();
  406. }
  407. psv->QueryInterface(IID_PPV_ARG(IFolderView, &_pfv)); // capture this
  408. psv->Release();
  409. }
  410. }
  411. }
  412. else
  413. {
  414. ATOMICRELEASE(_pfv); // break ref cycle
  415. }
  416. return S_OK;
  417. }
  418. STDMETHODIMP CPreview::Invoke(DISPID dispidMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS* pdispparams,
  419. VARIANT* pvarResult, EXCEPINFO* pexcepinfo, UINT* puArgErr)
  420. {
  421. HRESULT hr = S_OK;
  422. if (dispidMember == DISPID_FOCUSCHANGED)
  423. {
  424. hr = _ProcessSelection();
  425. }
  426. else
  427. {
  428. hr = CStockPropImpl<CPreview, IPreview2, &IID_IPreview2, &LIBID_PREVIEWLib>::Invoke(dispidMember, riid, lcid, wFlags, pdispparams, pvarResult, pexcepinfo, puArgErr);
  429. }
  430. return hr;
  431. }
  432. STDMETHODIMP CPreview::SetWallpaper(BSTR bstrPath)
  433. {
  434. return m_cwndPreview.SetWallpaper(bstrPath);
  435. }
  436. STDMETHODIMP CPreview::SaveAs(BSTR bstrPath)
  437. {
  438. return m_cwndPreview.SaveAs(bstrPath);
  439. }
  440. BOOL CPreview::IsHostLocalZone(DWORD dwFlags, HRESULT * phr)
  441. {
  442. HRESULT hr = E_ACCESSDENIED;
  443. CComPtr<IDefViewSafety> spDefViewSafety;
  444. if (SUCCEEDED(IUnknown_QueryService(m_spClientSite, SID_SFolderView,
  445. IID_PPV_ARG(IDefViewSafety, &spDefViewSafety))))
  446. {
  447. hr = spDefViewSafety->IsSafePage();
  448. }
  449. if (phr)
  450. {
  451. *phr = hr;
  452. }
  453. return (S_OK == hr) ? TRUE : FALSE;
  454. }
  455. STDMETHODIMP CPreview::_ProcessSelection(void)
  456. {
  457. if (_pfv)
  458. {
  459. int iItem;
  460. if (S_OK == _pfv->GetFocusedItem(&iItem))
  461. {
  462. LPITEMIDLIST pidlFile;
  463. if (SUCCEEDED(_pfv->Item(iItem, &pidlFile)))
  464. {
  465. IShellFolder *psf;
  466. if (SUCCEEDED(_pfv->GetFolder(IID_PPV_ARG(IShellFolder, &psf))))
  467. {
  468. TCHAR szPath[MAX_PATH];
  469. if (SUCCEEDED(DisplayNameOf(psf, pidlFile, SHGDN_FORPARSING, szPath, ARRAYSIZE(szPath))))
  470. {
  471. ShowFile(szPath, 1);
  472. }
  473. psf->Release();
  474. }
  475. ILFree(pidlFile);
  476. }
  477. }
  478. else
  479. {
  480. ShowFile(NULL, 0);
  481. }
  482. }
  483. return S_OK;
  484. }