|
|
#include "precomp.h"
#include <shimgvw.h>
#include "PrevCtrl.h"
#include "autosecurity.h"
#include <dispex.h>
#pragma hdrstop
LRESULT CPreview::OnCreate(UINT , WPARAM , LPARAM , BOOL&) { ATLTRACE(_T("CPreview::OnCreate\n"));
// Create the preview window
RECT rcWnd; GetClientRect(&rcWnd); if (m_cwndPreview.Create(m_hWnd, rcWnd, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, 0)) { m_cwndPreview.SetNotify(this);
HPALETTE hpal; if (SUCCEEDED(GetAmbientPalette(hpal))) m_cwndPreview.SetPalette(hpal);
return 0; }
return -1; }
LRESULT CPreview::OnActivate(UINT , WPARAM , LPARAM , BOOL& bHandled) { ATLTRACE(_T("CPreview::OnActivate\n")); m_cwndPreview.SetFocus(); bHandled = false; return 0; }
HRESULT CPreview::OnDrawAdvanced(ATL_DRAWINFO&) { ATLTRACE(_T("CPreview::OnDrawAdvanced\n")); return S_OK; }
LRESULT CPreview::OnEraseBkgnd(UINT , WPARAM , LPARAM , BOOL&) { ATLTRACE(_T("CPreview::OnEraseBkgnd\n")); return TRUE; }
LRESULT CPreview::OnSize(UINT , WPARAM , LPARAM lParam, BOOL&) { ATLTRACE(_T("CPreview::OnSize\n")); ::SetWindowPos(m_cwndPreview.m_hWnd, NULL, 0,0, LOWORD(lParam), HIWORD(lParam), SWP_NOZORDER | SWP_NOACTIVATE); return 0; }
// IObjectSafety::GetInterfaceSafetyOptions
//
// This method never gets called. We are safe for any and every thing. There should
// be no possible way that this control could lose, destroy, or expose data.
STDMETHODIMP CPreview::GetInterfaceSafetyOptions(REFIID riid, DWORD *pdwSupportedOptions, DWORD *pdwEnabledOptions) { ATLTRACE(_T("IObjectSafetyImpl::GetInterfaceSafetyOptions\n")); HRESULT hr; hr = IObjectSafetyImpl<CPreview, INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA>::GetInterfaceSafetyOptions(riid, pdwSupportedOptions, pdwEnabledOptions); if (SUCCEEDED(hr)) { IsHostLocalZone(CAS_REG_VALIDATION, &hr); } return hr; }
STDMETHODIMP CPreview::SetInterfaceSafetyOptions(REFIID riid, DWORD dwSupportedOptions, DWORD dwEnabledOptions) { ATLTRACE(_T("IObjectSafetyImpl::SetInterfaceSafetyOptions\n")); HRESULT hr; hr = IObjectSafetyImpl<CPreview, INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA>::SetInterfaceSafetyOptions(riid, dwSupportedOptions, dwEnabledOptions); if (SUCCEEDED(hr)) { IsHostLocalZone(CAS_REG_VALIDATION, &hr); } return hr; }
// IPersistPropertyBag::Load
//
// We have the following properties that we can load from the property bag:
// Toolbar false/zero = don't show the toolbar, otherwise show the toolbar
// Full Screen false/zero = don't show fullscreen button on toolbar, otherwise show the button
// Context Menu false/zero = don't show context menu, otherwise show the context menu when the user right clicks
// Print Button false/zero = don't show print button on toolbar, otherwise show the button
STDMETHODIMP CPreview::Load(IPropertyBag * pPropBag, IErrorLog * pErrorLog) { HRESULT hr; VARIANT var; BOOL bDummy = TRUE;
var.vt = VT_UI4; var.ulVal = TRUE; hr = pPropBag->Read(L"Toolbar", &var, NULL); if (SUCCEEDED(hr) && var.vt==VT_UI4) { m_cwndPreview.IV_OnSetOptions(IV_SETOPTIONS,IVO_TOOLBAR,var.ulVal,bDummy); }
var.vt = VT_UI4; var.ulVal = TRUE; hr = pPropBag->Read(L"Full Screen", &var, NULL); if (SUCCEEDED(hr) && var.vt==VT_UI4) { m_cwndPreview.IV_OnSetOptions(IV_SETOPTIONS,IVO_FULLSCREENBTN,var.ulVal,bDummy); }
var.vt = VT_UI4; var.ulVal = TRUE; hr = pPropBag->Read(L"Print Button", &var, NULL); if (SUCCEEDED(hr) && var.vt==VT_UI4) { m_cwndPreview.IV_OnSetOptions(IV_SETOPTIONS,IVO_PRINTBTN,var.ulVal,bDummy); }
var.vt = VT_UI4; var.ulVal = TRUE; hr = pPropBag->Read(L"Context Menu", &var, NULL); if (SUCCEEDED(hr) && var.vt==VT_UI4) { m_cwndPreview.IV_OnSetOptions(IV_SETOPTIONS,IVO_CONTEXTMENU,var.ulVal,bDummy); }
var.vt = VT_UI4; var.ulVal = FALSE; hr = pPropBag->Read(L"Allow Online", &var, NULL); if (SUCCEEDED(hr) && var.vt==VT_UI4) { m_cwndPreview.IV_OnSetOptions(IV_SETOPTIONS,IVO_ALLOWGOONLINE,var.ulVal,bDummy); }
var.vt = VT_UI4; var.ulVal = FALSE; hr = pPropBag->Read(L"Disable Edit", &var, NULL); if (SUCCEEDED(hr) && var.vt==VT_UI4) { m_cwndPreview.IV_OnSetOptions(IV_SETOPTIONS,IVO_DISABLEEDIT,var.ulVal,bDummy); }
return S_OK; }
// If we are initialized via IStream, read a DWORD from the stream that is a mask
// for which toolbar buttons to show
STDMETHODIMP CPreview::Load(IStream *pStream) { DWORD dwFlags = 0; ULONG ulRead = 0; BOOL bDummy = TRUE; if (SUCCEEDED(pStream->Read(&dwFlags, sizeof(dwFlags), &ulRead)) && ulRead == sizeof(dwFlags)) { m_cwndPreview.IV_OnSetOptions(IV_SETOPTIONS,IVO_TOOLBAR,dwFlags & PVTB_TOOLBAR, bDummy); m_cwndPreview.IV_OnSetOptions(IV_SETOPTIONS,IVO_FULLSCREENBTN,dwFlags & PVTB_HIDEFULLSCREEN, bDummy); m_cwndPreview.IV_OnSetOptions(IV_SETOPTIONS,IVO_PRINTBTN,dwFlags & PVTB_HIDEPRINTBTN, bDummy); m_cwndPreview.IV_OnSetOptions(IV_SETOPTIONS,IVO_CONTEXTMENU,dwFlags & PVTB_CONTEXTMENU, bDummy); m_cwndPreview.IV_OnSetOptions(IV_SETOPTIONS,IVO_ALLOWGOONLINE,dwFlags & PVTB_ALLOWONLINE, bDummy); m_cwndPreview.IV_OnSetOptions(IV_SETOPTIONS,IVO_DISABLEEDIT,dwFlags & PVTB_DISABLEEDIT, bDummy); } return S_OK;
}
// IPreview Methods:
STDMETHODIMP CPreview::ShowFile(BSTR bstrFileName) { m_cwndPreview.ShowFile(bstrFileName, 1); return S_OK; }
STDMETHODIMP CPreview::ShowFile(BSTR bstrFileName, int iSelectCount) { m_cwndPreview.ShowFile(bstrFileName, iSelectCount); return S_OK; }
STDMETHODIMP CPreview::Show(VARIANT var) { HRESULT hr; switch (var.vt) { case VT_UNKNOWN: case VT_DISPATCH: // QI for Folder Item
if (var.punkVal) { FolderItems *pfis; FolderItem *pfi; hr = var.punkVal->QueryInterface(IID_PPV_ARG(FolderItem, &pfi)); if (SUCCEEDED(hr)) { // If the item is a link we want to get the link's target:
VARIANT_BOOL vbool; hr = pfi->get_IsLink(&vbool); if (SUCCEEDED(hr) && (VARIANT_FALSE != vbool)) // IsLink returns TRUE, not VARIANT_TRUE
{ IDispatch *pdisp; hr = pfi->get_GetLink(&pdisp); if (SUCCEEDED(hr) && pdisp) { IShellLinkDual2 * psl2; hr = pdisp->QueryInterface(IID_PPV_ARG(IShellLinkDual2, &psl2)); if (SUCCEEDED(hr) && psl2) { FolderItem * pfiTarg; hr = psl2->get_Target(&pfiTarg); if (SUCCEEDED(hr) && pfiTarg) { pfi->Release(); pfi = pfiTarg; } psl2->Release(); } pdisp->Release(); } }
// Now we need to know the path for this item. We can only view items if
// we can get a path or URL to the target so some namespaces aren't viewable.
BSTR bstr; hr = pfi->get_Path(&bstr); if (SUCCEEDED(hr)) { m_cwndPreview.ShowFile(bstr, 1); SysFreeString(bstr); hr = S_OK; } else { // we couldn't get the path so we will display the "No Preview" message
m_cwndPreview.ShowFile(NULL, 1); hr = S_FALSE; }
// now release the Folder Item pointer
pfi->Release();
return hr; } else if (SUCCEEDED(var.punkVal->QueryInterface(IID_PPV_ARG(FolderItems, &pfis)))) { // currently in the multi-select case we just show the multi-select message.
// eventually this should go to slideshow mode
m_cwndPreview.ShowFile(NULL, 2); pfis->Release(); return S_FALSE; } } // the unknown pointer isn't for an object type that we know about
return E_INVALIDARG;
case VT_BSTR: m_cwndPreview.ShowFile(var.bstrVal, 1); break;
case VT_BOOL: // show(false) will hide the currently previewed item
if (VARIANT_FALSE == var.boolVal) { m_cwndPreview.ShowFile(NULL, 0); return S_OK; } else { return E_INVALIDARG; }
default: return E_INVALIDARG; }
return S_OK; }
//*** IsVK_TABCycler -- is key a TAB-equivalent
// ENTRY/EXIT
// dir 0 if not a TAB, non-0 if a TAB
// NOTES
// NYI: -1 for shift+tab, 1 for tab
// cloned from browseui/util.cpp
//
int IsVK_TABCycler(MSG *pMsg) { if (!pMsg) return 0;
if (pMsg->message != WM_KEYDOWN) return 0; if (! (pMsg->wParam == VK_TAB || pMsg->wParam == VK_F6)) return 0;
#if 0 // todo?
return (GetAsyncKeyState(VK_SHIFT) < 0) ? -1 : 1; #endif
return 1; }
//***
// NOTES
// hard-coded 1/2/4 (vs. KEYMOD_*) is same thing atlctl.h does. go figure...
DWORD GetGrfMods() { DWORD dwMods;
dwMods = 0; if (GetAsyncKeyState(VK_SHIFT) < 0) dwMods |= 1; // KEYMOD_SHIFT
if (GetAsyncKeyState(VK_CONTROL) < 0) dwMods |= 2; // KEYMOD_CONTROL
if (GetAsyncKeyState(VK_MENU) < 0) dwMods |= 4; // KEYMOD_MENU
return dwMods; }
STDMETHODIMP CPreview::TranslateAccelerator(LPMSG lpmsg) { ATLTRACE(_T("CPreview::TranslateAccelerator\n"));
if (m_cwndPreview.TranslateAccelerator(lpmsg)) { return S_OK; }
if (IsVK_TABCycler(lpmsg)) { // REVIEW: looks like newer versions of ATL might do this for us so
// possibly we can replace w/ call to SUPER::TA when we upgrade.
CComQIPtr <IOleControlSite, &IID_IOleControlSite> spOCS(m_spClientSite); if (spOCS) { return spOCS->TranslateAccelerator(lpmsg, GetGrfMods()); } }
return S_FALSE; }
STDMETHODIMP CPreview::OnFrameWindowActivate(BOOL fActive) { if (fActive) { m_cwndPreview.SetFocus(); } return S_OK; }
LRESULT CPreview::OnSetFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { ATLTRACE(_T("CPreview::OnSetFocus\n")); LRESULT ret = CComControl<CPreview>::OnSetFocus(uMsg,wParam,lParam, bHandled); m_cwndPreview.SetFocus(); return ret; }
STDMETHODIMP CPreview::get_printable(BOOL * pVal) { // If we don't trust the host, we tell them it is always printable because we don't
// want them to be able to see if the file exists on the disk. Hackers can use
// this to determine where the OS is installed and which apps are installed.
*pVal = TRUE;
if (IsHostLocalZone(CAS_REG_VALIDATION, NULL)) { *pVal = m_cwndPreview.GetPrintable(); }
return S_OK; }
STDMETHODIMP CPreview::put_printable(BOOL newVal) { return S_FALSE; }
STDMETHODIMP CPreview::get_cxImage(long * pVal) { // REVIEW: Return an error and set output to zero if no image is currently displayed?
*pVal = m_cwndPreview.m_ctlPreview.m_cxImage;
return S_OK; }
STDMETHODIMP CPreview::get_cyImage(long * pVal) { // REVIEW: Return an error and set output to zero if no image is currently displayed?
*pVal = m_cwndPreview.m_ctlPreview.m_cyImage;
return S_OK; }
STDMETHODIMP CPreview::Zoom(int iDirection) { switch (iDirection) { case -1: m_cwndPreview.ZoomOut(); break;
case 0: return S_OK;
case 1: m_cwndPreview.ZoomIn(); break;
default: return S_FALSE; }
return S_OK; }
STDMETHODIMP CPreview::BestFit() { m_cwndPreview.BestFit(); return S_OK; }
STDMETHODIMP CPreview::ActualSize() { m_cwndPreview.ActualSize(); return S_OK; }
STDMETHODIMP CPreview::SlideShow() { HRESULT hr = m_cwndPreview.StartSlideShow(NULL); return SUCCEEDED(hr) ? S_OK : S_FALSE; }
STDMETHODIMP CPreview::Rotate(DWORD dwAngle) { HRESULT hr = m_cwndPreview.Rotate(dwAngle); return SUCCEEDED(hr) ? S_OK : S_FALSE; }
STDMETHODIMP CPreview::SetClientSite(IOleClientSite *pClientSite) { IOleObjectImpl<CPreview>::SetClientSite(pClientSite); m_cwndPreview.SetSite(pClientSite);
return S_OK; }
STDMETHODIMP CPreview::SetSite(IUnknown* punkSite) { IObjectWithSiteImpl<CPreview>::SetSite(punkSite); m_cwndPreview.SetSite(punkSite);
if (punkSite) { if (!_pfv) { IShellView *psv; if (SUCCEEDED(IUnknown_QueryService(punkSite, SID_DefView, IID_PPV_ARG(IShellView, &psv)))) { IDispatch *pdisp; if (SUCCEEDED(psv->GetItemObject(SVGIO_BACKGROUND, IID_PPV_ARG(IDispatch, &pdisp)))) { ConnectToConnectionPoint(SAFECAST(this, IPreview2 *), DIID_DShellFolderViewEvents, TRUE, pdisp, &_dwConnectionCookie, NULL); _ProcessSelection(); pdisp->Release(); }
psv->QueryInterface(IID_PPV_ARG(IFolderView, &_pfv)); // capture this
psv->Release(); } } } else { ATOMICRELEASE(_pfv); // break ref cycle
} return S_OK; }
STDMETHODIMP CPreview::Invoke(DISPID dispidMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS* pdispparams, VARIANT* pvarResult, EXCEPINFO* pexcepinfo, UINT* puArgErr) { HRESULT hr = S_OK;
if (dispidMember == DISPID_FOCUSCHANGED) { hr = _ProcessSelection(); } else { hr = CStockPropImpl<CPreview, IPreview2, &IID_IPreview2, &LIBID_PREVIEWLib>::Invoke(dispidMember, riid, lcid, wFlags, pdispparams, pvarResult, pexcepinfo, puArgErr); }
return hr; }
STDMETHODIMP CPreview::SetWallpaper(BSTR bstrPath) { return m_cwndPreview.SetWallpaper(bstrPath); }
STDMETHODIMP CPreview::SaveAs(BSTR bstrPath) { return m_cwndPreview.SaveAs(bstrPath); }
BOOL CPreview::IsHostLocalZone(DWORD dwFlags, HRESULT * phr) { HRESULT hr = E_ACCESSDENIED; CComPtr<IDefViewSafety> spDefViewSafety; if (SUCCEEDED(IUnknown_QueryService(m_spClientSite, SID_SFolderView, IID_PPV_ARG(IDefViewSafety, &spDefViewSafety)))) { hr = spDefViewSafety->IsSafePage(); }
if (phr) { *phr = hr; }
return (S_OK == hr) ? TRUE : FALSE; }
STDMETHODIMP CPreview::_ProcessSelection(void) { if (_pfv) { int iItem; if (S_OK == _pfv->GetFocusedItem(&iItem)) { LPITEMIDLIST pidlFile; if (SUCCEEDED(_pfv->Item(iItem, &pidlFile))) { IShellFolder *psf; if (SUCCEEDED(_pfv->GetFolder(IID_PPV_ARG(IShellFolder, &psf)))) { TCHAR szPath[MAX_PATH];
if (SUCCEEDED(DisplayNameOf(psf, pidlFile, SHGDN_FORPARSING, szPath, ARRAYSIZE(szPath)))) { ShowFile(szPath, 1); }
psf->Release(); }
ILFree(pidlFile); } } else { ShowFile(NULL, 0); } }
return S_OK; }
|