|
|
//+-------------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (C) Microsoft Corporation, 2000
//
// File: cpuiele.cpp
//
// This module contains the following classes:
//
// CCplUiElement
// CCplUiCommand
// CCplUiCommandOnPidl
//
// CCplUiElement is an implementation of IUIElement. This provides
// the necessary display information for use in the shell's webview
// implementation. The class also implements ICpUiElementInfo which
// is similar to IUIElement but provides the display information in
// a more 'final' form than a "<module>,<resource>" format.
// The ICpUiElementInfo interface is used internally by the Control Panel
// implementation.
//
// CCplUiCommand is an implementation of IUICommand. As with IUIElement,
// this provides the necessary functions for communicating with webview
// as a 'command' object (i.e. selectable 'link'). Also as with the
// previous class, CCplUiCommand implements an internal version of
// the public interface. ICplUiCommand provides two things:
// 1. A method to invoke a context menu.
// 2. An invocation method that accepts a site pointer. This site
// pointer is passed along to an 'action' object that may need
// access to the shell browser to perform it's function. It
// obtains access to the shell browser through this site ptr.
//
// CCplUiCommandOnPidl is another implementation of IUICommand that
// wraps a shell item ID list. It is used to represent the CPL
// applet items in a category view.
//
//--------------------------------------------------------------------------
#include "shellprv.h"
#include "cpviewp.h"
#include "cpguids.h"
#include "cpuiele.h"
#include "cputil.h"
#include "contextmenu.h"
#include "prop.h"
namespace CPL {
//-----------------------------------------------------------------------------
// CCplUiElement
//-----------------------------------------------------------------------------
class CCplUiElement : public IUIElement, public ICpUiElementInfo { public: //
// IUnknown
//
STDMETHOD(QueryInterface)(REFIID riid, void **ppv); STDMETHOD_(ULONG, AddRef)(void); STDMETHOD_(ULONG, Release)(void); //
// IUIElement (used by shell webview)
//
STDMETHOD(get_Name)(IShellItemArray *psiItemArray, LPWSTR *ppszName); STDMETHOD(get_Icon)(IShellItemArray *psiItemArray, LPWSTR *ppszIcon); STDMETHOD(get_Tooltip)(IShellItemArray *psiItemArray, LPWSTR *ppszInfotip); //
// ICpUiElementInfo (used internally by Control Panel)
//
STDMETHOD(LoadIcon)(eCPIMGSIZE eSize, HICON *phIcon); STDMETHOD(LoadName)(LPWSTR *ppszName); STDMETHOD(LoadTooltip)(LPWSTR *ppszTooltip);
static HRESULT CreateInstance(LPCWSTR pszName, LPCWSTR pszInfotip, LPCWSTR pszIcon, REFIID riid, void **ppvOut);
protected: CCplUiElement(LPCWSTR pszName, LPCWSTR pszInfotip, LPCWSTR pszIcon); CCplUiElement(void); virtual CCplUiElement::~CCplUiElement(void);
private: LONG m_cRef; LPCWSTR m_pszName; LPCWSTR m_pszInfotip; LPCWSTR m_pszIcon;
HRESULT _GetResourceString(LPCWSTR pszItem, LPWSTR *ppsz); HRESULT _GetIconResource(LPWSTR *ppsz); HRESULT _GetNameResource(LPWSTR *ppsz); HRESULT _GetInfotipResource(LPWSTR *ppsz); };
CCplUiElement::CCplUiElement( LPCWSTR pszName, LPCWSTR pszInfotip, // NULL == No Info Tip
LPCWSTR pszIcon ) : m_cRef(1), m_pszName(pszName), m_pszInfotip(pszInfotip), m_pszIcon(pszIcon) { ASSERT(IS_INTRESOURCE(m_pszName) || !IsBadStringPtr(m_pszName, UINT_PTR(-1))); ASSERT((NULL == pszInfotip) || IS_INTRESOURCE(m_pszInfotip) || !IsBadStringPtr(m_pszInfotip, UINT_PTR(-1))); ASSERT(IS_INTRESOURCE(m_pszIcon) || !IsBadStringPtr(m_pszIcon, UINT_PTR(-1))); }
CCplUiElement::CCplUiElement( void ) : m_cRef(1), m_pszName(NULL), m_pszInfotip(NULL), m_pszIcon(NULL) { TraceMsg(TF_LIFE, "CCplUiElement::CCplUiElement, this = 0x%x", this); }
CCplUiElement::~CCplUiElement( void ) { TraceMsg(TF_LIFE, "CCplUiElement::~CCplUiElement, this = 0x%x", this); //
// Note that the member string pointers contain either a resource ID
// or a pointer to constant memory.
// Therefore, we do not try to free them.
//
}
HRESULT CCplUiElement::CreateInstance( // [static]
LPCWSTR pszName, LPCWSTR pszInfotip, LPCWSTR pszIcon, REFIID riid, void **ppvOut ) { ASSERT(NULL != ppvOut); ASSERT(!IsBadWritePtr(ppvOut, sizeof(*ppvOut)));
*ppvOut = NULL;
HRESULT hr = E_OUTOFMEMORY; CCplUiElement *pe = new CCplUiElement(pszName, pszInfotip, pszIcon); if (NULL != pe) { hr = pe->QueryInterface(riid, ppvOut); pe->Release(); } return THR(hr); }
STDMETHODIMP CCplUiElement::QueryInterface( REFIID riid, void **ppv ) { ASSERT(NULL != ppv); ASSERT(!IsBadWritePtr(ppv, sizeof(*ppv)));
static const QITAB qit[] = { QITABENT(CCplUiElement, IUIElement), QITABENT(CCplUiElement, ICpUiElementInfo), { 0 }, }; HRESULT hr = QISearch(this, qit, riid, ppv);
return E_NOINTERFACE == hr ? hr : THR(hr); }
STDMETHODIMP_(ULONG) CCplUiElement::AddRef( void ) { return InterlockedIncrement(&m_cRef); }
STDMETHODIMP_(ULONG) CCplUiElement::Release( void ) { ASSERT( 0 != m_cRef ); ULONG cRef = InterlockedDecrement(&m_cRef); if ( 0 == cRef ) { delete this; } return cRef; }
STDMETHODIMP CCplUiElement::get_Name( IShellItemArray *psiItemArray, LPWSTR *ppszName ) { UNREFERENCED_PARAMETER(psiItemArray);
HRESULT hr = LoadName(ppszName); return THR(hr); }
STDMETHODIMP CCplUiElement::get_Icon( IShellItemArray *psiItemArray, LPWSTR *ppszIcon ) { UNREFERENCED_PARAMETER(psiItemArray);
HRESULT hr = _GetIconResource(ppszIcon); return THR(hr); }
STDMETHODIMP CCplUiElement::get_Tooltip( IShellItemArray *psiItemArray, LPWSTR *ppszInfotip ) { UNREFERENCED_PARAMETER(psiItemArray); HRESULT hr = THR(LoadTooltip(ppszInfotip)); if (S_FALSE == hr) { //
// Tooltips are optional but we need to return a failure
// code to tell webview that we don't have one.
//
hr = E_FAIL; } return hr; }
STDMETHODIMP CCplUiElement::LoadIcon( eCPIMGSIZE eSize, HICON *phIcon ) { *phIcon = NULL;
LPWSTR pszResource; HRESULT hr = _GetIconResource(&pszResource); if (SUCCEEDED(hr)) { hr = CPL::LoadIconFromResource(pszResource, eSize, phIcon); CoTaskMemFree(pszResource); } return THR(hr); }
STDMETHODIMP CCplUiElement::LoadName( LPWSTR *ppszName ) { LPWSTR pszResource; HRESULT hr = _GetNameResource(&pszResource); if (SUCCEEDED(hr)) { hr = CPL::LoadStringFromResource(pszResource, ppszName); CoTaskMemFree(pszResource); } return THR(hr); }
STDMETHODIMP CCplUiElement::LoadTooltip( LPWSTR *ppszTooltip ) { LPWSTR pszResource; HRESULT hr = _GetInfotipResource(&pszResource); if (S_OK == hr) { hr = CPL::LoadStringFromResource(pszResource, ppszTooltip); CoTaskMemFree(pszResource); } return THR(hr); }
HRESULT CCplUiElement::_GetIconResource( LPWSTR *ppsz ) { HRESULT hr = _GetResourceString(m_pszIcon, ppsz); return THR(hr); }
HRESULT CCplUiElement::_GetNameResource( LPWSTR *ppsz ) { HRESULT hr = _GetResourceString(m_pszName, ppsz); return THR(hr); }
//
// Returns S_FALSE if tooltip text is not provided.
// Tooltips are optional. For example, the "learn about"
// tasks in Control Panel's web view pane do not have tooltip
// text.
//
HRESULT CCplUiElement::_GetInfotipResource( LPWSTR *ppsz ) { HRESULT hr = S_FALSE; if (NULL != m_pszInfotip) { hr = _GetResourceString(m_pszInfotip, ppsz); } return THR(hr); }
//
// On successful return, caller must free returned string using
// CoTaskMemFree.
//
HRESULT CCplUiElement::_GetResourceString( LPCWSTR pszItem, LPWSTR *ppsz ) { ASSERT(NULL != ppsz); ASSERT(!IsBadWritePtr(ppsz, sizeof(*ppsz)));
*ppsz = NULL; HRESULT hr = E_FAIL;
if (IS_INTRESOURCE(pszItem)) { //
// pszItem is a resource identifier integer. Create a resource
// ID string "<module>,<-i>" for the resource.
//
WCHAR szModule[MAX_PATH]; if (GetModuleFileNameW(HINST_THISDLL, szModule, ARRAYSIZE(szModule))) { const size_t cchResource = lstrlenW(szModule) + 15; *ppsz = (LPWSTR)CoTaskMemAlloc(cchResource * sizeof(WCHAR)); if (NULL != *ppsz) { //
// Precede the resource ID with a minus sign so that it will be
// treated as a resource ID and not an index.
//
hr = StringCchPrintfW(*ppsz, cchResource, L"%s,-%u", szModule, PtrToUint(pszItem)); } else { hr = E_OUTOFMEMORY; } } else { hr = ResultFromLastError(); } } else { //
// pszItem is a text string. Assume it's in the form of
// "<module>,<-i>". Simply duplicate it.
//
ASSERT(!IsBadStringPtr(pszItem, UINT_PTR(-1)));
hr = SHStrDup(pszItem, ppsz); } return THR(hr); }
//-----------------------------------------------------------------------------
// CCplUiCommand
//-----------------------------------------------------------------------------
class CCplUiCommand : public CObjectWithSite, public CCplUiElement, public IUICommand, public ICpUiCommand { public: //
// IUnknown
//
STDMETHOD(QueryInterface)(REFIID riid, void **ppv); STDMETHOD_(ULONG, AddRef)(void) { return CCplUiElement::AddRef(); } STDMETHOD_(ULONG, Release)(void) { return CCplUiElement::Release(); } //
// IUICommand
//
STDMETHOD(get_Name)(IShellItemArray *psiItemArray, LPWSTR *ppszName) { return CCplUiElement::get_Name(psiItemArray, ppszName); } STDMETHOD(get_Icon)(IShellItemArray *psiItemArray, LPWSTR *ppszIcon) { return CCplUiElement::get_Icon(psiItemArray, ppszIcon); } STDMETHOD(get_Tooltip)(IShellItemArray *psiItemArray, LPWSTR *ppszInfotip) { return CCplUiElement::get_Tooltip(psiItemArray, ppszInfotip); } STDMETHOD(get_CanonicalName)(GUID *pguidCommandName); STDMETHOD(get_State)(IShellItemArray *psiItemArray, BOOL fOkToBeSlow, UISTATE *puisState); STDMETHOD(Invoke)(IShellItemArray *psiItemArray, IBindCtx *pbc); //
// ICpUiCommand
//
STDMETHOD(InvokeContextMenu)(HWND hwndParent, const POINT *ppt); STDMETHOD(Invoke)(HWND hwndParent, IUnknown *punkSite); STDMETHOD(GetDataObject)(IDataObject **ppdtobj); //
// ICpUiElementInfo
//
STDMETHOD(LoadIcon)(eCPIMGSIZE eSize, HICON *phIcon) { return CCplUiElement::LoadIcon(eSize, phIcon); } STDMETHOD(LoadName)(LPWSTR *ppszName) { return CCplUiElement::LoadName(ppszName); } STDMETHOD(LoadTooltip)(LPWSTR *ppszTooltip) { return CCplUiElement::LoadTooltip(ppszTooltip); }
static HRESULT CreateInstance(LPCWSTR pszName, LPCWSTR pszInfotip, LPCWSTR pszIcon, const IAction *pAction, REFIID riid, void **ppvOut);
protected: CCplUiCommand(LPCWSTR pszName, LPCWSTR pszInfotip, LPCWSTR pszIcon, const IAction *pAction); CCplUiCommand(void); ~CCplUiCommand(void);
private: const IAction *m_pAction;
HRESULT _IsCommandRestricted(void); };
CCplUiCommand::CCplUiCommand( void ) : m_pAction(NULL) { TraceMsg(TF_LIFE, "CCplUiCommand::CCplUiCommand, this = 0x%x", this); }
CCplUiCommand::CCplUiCommand( LPCWSTR pszName, LPCWSTR pszInfotip, LPCWSTR pszIcon, const IAction *pAction ) : CCplUiElement(pszName, pszInfotip, pszIcon), m_pAction(pAction) { TraceMsg(TF_LIFE, "CCplUiCommand::CCplUiCommand, this = 0x%x", this); }
CCplUiCommand::~CCplUiCommand( void ) { TraceMsg(TF_LIFE, "CCplUiCommand::~CCplUiCommand, this = 0x%x", this); //
// Note that m_pAction is a pointer to a const object.
// Therefore, we don't try to free it.
//
}
HRESULT CCplUiCommand::CreateInstance( // [static]
LPCWSTR pszName, LPCWSTR pszInfotip, LPCWSTR pszIcon, const IAction *pAction, REFIID riid, void **ppvOut ) { ASSERT(NULL != ppvOut); ASSERT(!IsBadWritePtr(ppvOut, sizeof(*ppvOut)));
*ppvOut = NULL;
HRESULT hr = E_OUTOFMEMORY; CCplUiCommand *pc = new CCplUiCommand(pszName, pszInfotip, pszIcon, pAction); if (NULL != pc) { hr = pc->QueryInterface(riid, ppvOut); pc->Release(); } return THR(hr); }
STDMETHODIMP CCplUiCommand::QueryInterface( REFIID riid, void **ppv ) { ASSERT(NULL != ppv); ASSERT(!IsBadWritePtr(ppv, sizeof(*ppv)));
static const QITAB qit[] = { QITABENT(CCplUiCommand, IUICommand), QITABENT(CCplUiCommand, ICpUiElementInfo), QITABENT(CCplUiCommand, ICpUiCommand), QITABENT(CCplUiCommand, IObjectWithSite), QITABENTMULTI(CCplUiCommand, IUIElement, IUICommand), { 0 }, }; HRESULT hr = QISearch(this, qit, riid, ppv);
return E_NOINTERFACE == hr ? hr : THR(hr); }
STDMETHODIMP CCplUiCommand::get_CanonicalName( GUID *pguidCommandName ) { UNREFERENCED_PARAMETER(pguidCommandName); //
// This function is unimplemented. It is in IUICommand to
// support generic functionality in the shell. This functionality
// is not applicable to the use of IUICommand in the Control
// Panel.
//
return E_NOTIMPL; }
STDMETHODIMP CCplUiCommand::get_State( IShellItemArray *psiItemArray, BOOL fOkToBeSlow, UISTATE *puisState ) { ASSERT(NULL != m_pAction); ASSERT(NULL != puisState); ASSERT(!IsBadWritePtr(puisState, sizeof(*puisState)));
UNREFERENCED_PARAMETER(psiItemArray);
*puisState = UIS_DISABLED; // default;
//
// If an action is restricted, we hide it's corresponding
// UI element in the user interface.
//
HRESULT hr = _IsCommandRestricted(); if (SUCCEEDED(hr)) { switch(hr) { case S_OK: *puisState = UIS_HIDDEN; break;
case S_FALSE: *puisState = UIS_ENABLED;
default: break; } //
// Don't propagate S_FALSE to caller.
//
hr = S_OK; } return THR(hr); }
//
// IUICommand::Invoke
// This version is called by webview when the user selects an
// item from a webview menu.
//
STDMETHODIMP CCplUiCommand::Invoke( IShellItemArray *psiItemArray, IBindCtx *pbc ) { DBG_ENTER(FTF_CPANEL, "CCplUiCommand::Invoke");
ASSERT(NULL != m_pAction);
UNREFERENCED_PARAMETER(psiItemArray); UNREFERENCED_PARAMETER(pbc);
HRESULT hr = m_pAction->Execute(NULL, _punkSite);
DBG_EXIT_HRES(FTF_CPANEL, "CCplUiCommand::Invoke", hr); return THR(hr); }
//
// ICpUiCommand::Invoke
// This version is called by CLinkElement::_OnSelected when
// the user selects either a category task or a category item
// in the category choice view.
//
STDMETHODIMP CCplUiCommand::Invoke( HWND hwndParent, IUnknown *punkSite ) { ASSERT(NULL != m_pAction);
HRESULT hr = m_pAction->Execute(hwndParent, punkSite); return THR(hr); }
STDMETHODIMP CCplUiCommand::InvokeContextMenu( HWND hwndParent, const POINT *ppt ) { //
// Only commands on pidls provide a context menu.
//
UNREFERENCED_PARAMETER(hwndParent); UNREFERENCED_PARAMETER(ppt); return E_NOTIMPL; }
STDMETHODIMP CCplUiCommand::GetDataObject( IDataObject **ppdtobj ) { //
// Simple UI commands don't provide a data object.
//
return E_NOTIMPL; }
//
// Returns:
// S_OK = Command is restricted.
// S_FALSE = Command is not restricted.
//
HRESULT CCplUiCommand::_IsCommandRestricted( void ) { //
// The ICplNamespace ptr is passed to IsRestricted in case the restriction
// code needs to inspect contents of the namespace. The "Other Cpl Options"
// link command uses this to determine if the "OTHER" category contains any
// CPL applets or not. If it contains no applets, the link is hidden (restricted).
//
ICplNamespace *pns; HRESULT hr = IUnknown_QueryService(_punkSite, SID_SControlPanelView, IID_ICplNamespace, (void **)&pns); if (SUCCEEDED(hr)) { hr = m_pAction->IsRestricted(pns); pns->Release(); } return THR(hr); }
//-----------------------------------------------------------------------------
// CCplUiCommandOnPidl
//-----------------------------------------------------------------------------
class CCplUiCommandOnPidl : public CObjectWithSite, public IUICommand, public ICpUiCommand, public ICpUiElementInfo, public IDataObject { public: ~CCplUiCommandOnPidl(void);
//
// IUnknown
//
STDMETHOD(QueryInterface)(REFIID riid, void **ppv); STDMETHOD_(ULONG, AddRef)(void); STDMETHOD_(ULONG, Release)(void); //
// IUICommand
//
STDMETHOD(get_Name)(IShellItemArray *psiItemArray, LPWSTR *ppszName); STDMETHOD(get_Icon)(IShellItemArray *psiItemArray, LPWSTR *ppszIcon); STDMETHOD(get_Tooltip)(IShellItemArray *psiItemArray, LPWSTR *ppszInfotip); STDMETHOD(get_CanonicalName)(GUID *pguidCommandName); STDMETHOD(get_State)(IShellItemArray *psiItemArray, BOOL fOkToBeSlow, UISTATE *puisState); STDMETHOD(Invoke)(IShellItemArray *psiItemArray, IBindCtx *pbc); //
// ICpUiCommand
//
STDMETHOD(InvokeContextMenu)(HWND hwndParent, const POINT *ppt); STDMETHOD(Invoke)(HWND hwndParent, IUnknown *punkSite); STDMETHOD(GetDataObject)(IDataObject **ppdtobj); //
// ICpUiElementInfo
//
STDMETHOD(LoadIcon)(eCPIMGSIZE eSize, HICON *phIcon); STDMETHOD(LoadName)(LPWSTR *ppszName); STDMETHOD(LoadTooltip)(LPWSTR *ppszTooltip); //
// IDataObject
//
STDMETHOD(GetData)(FORMATETC *pFmtEtc, STGMEDIUM *pstm); STDMETHOD(GetDataHere)(FORMATETC *pFmtEtc, STGMEDIUM *pstm); STDMETHOD(QueryGetData)(FORMATETC *pFmtEtc); STDMETHOD(GetCanonicalFormatEtc)(FORMATETC *pFmtEtcIn, FORMATETC *pFmtEtcOut); STDMETHOD(SetData)(FORMATETC *pFmtEtc, STGMEDIUM *pstm, BOOL fRelease); STDMETHOD(EnumFormatEtc)(DWORD dwDirection, LPENUMFORMATETC *ppEnum); STDMETHOD(DAdvise)(FORMATETC *pFmtEtc, DWORD grfAdv, LPADVISESINK pAdvSink, DWORD *pdwConnection); STDMETHOD(DUnadvise)(DWORD dwConnection); STDMETHOD(EnumDAdvise)(LPENUMSTATDATA *ppEnum);
static HRESULT CreateInstance(LPCITEMIDLIST pidl, REFIID riid, void **ppvOut);
private: LONG m_cRef; IShellFolder *m_psf; // Cached Control Panel IShellFolder ptr.
LPITEMIDLIST m_pidl; // Assumed to be relative to Control Panel.
IDataObject *m_pdtobj;
CCplUiCommandOnPidl(void);
HRESULT _GetControlPanelFolder(IShellFolder **ppsf); HRESULT _Initialize(LPCITEMIDLIST pidl); HRESULT _GetName(LPWSTR *ppszName); HRESULT _GetInfotip(LPWSTR *ppszInfotip); HRESULT _GetIconResource(LPWSTR *ppszIcon); HRESULT _Invoke(HWND hwndParent, IUnknown *punkSite); HRESULT _GetDataObject(IDataObject **ppdtobj); };
CCplUiCommandOnPidl::CCplUiCommandOnPidl( void ) : m_cRef(1), m_psf(NULL), m_pidl(NULL), m_pdtobj(NULL) { TraceMsg(TF_LIFE, "CCplUiCommandOnPidl::CCplUiCommandOnPidl, this = 0x%x", this); }
CCplUiCommandOnPidl::~CCplUiCommandOnPidl( void ) { TraceMsg(TF_LIFE, "CCplUiCommandOnPidl::~CCplUiCommandOnPidl, this = 0x%x", this); ATOMICRELEASE(m_psf); ATOMICRELEASE(m_pdtobj); if (NULL != m_pidl) { ILFree(m_pidl); } }
HRESULT CCplUiCommandOnPidl::CreateInstance( // [static]
LPCITEMIDLIST pidl, REFIID riid, void **ppvOut ) { ASSERT(NULL != ppvOut); ASSERT(!IsBadWritePtr(ppvOut, sizeof(*ppvOut))); ASSERT(NULL != pidl);
*ppvOut = NULL;
HRESULT hr = E_OUTOFMEMORY; CCplUiCommandOnPidl *pc = new CCplUiCommandOnPidl(); if (NULL != pc) { hr = pc->_Initialize(pidl); if (SUCCEEDED(hr)) { hr = pc->QueryInterface(riid, ppvOut); } pc->Release(); } return THR(hr); }
STDMETHODIMP CCplUiCommandOnPidl::QueryInterface( REFIID riid, void **ppv ) { ASSERT(NULL != ppv); ASSERT(!IsBadWritePtr(ppv, sizeof(*ppv)));
static const QITAB qit[] = { QITABENT(CCplUiCommandOnPidl, IUICommand), QITABENT(CCplUiCommandOnPidl, ICpUiCommand), QITABENT(CCplUiCommandOnPidl, ICpUiElementInfo), QITABENT(CCplUiCommandOnPidl, IObjectWithSite), QITABENT(CCplUiCommandOnPidl, IDataObject), QITABENTMULTI(CCplUiCommandOnPidl, IUIElement, IUICommand), { 0 }, }; HRESULT hr = QISearch(this, qit, riid, ppv);
return E_NOINTERFACE == hr ? hr : THR(hr); }
STDMETHODIMP_(ULONG) CCplUiCommandOnPidl::AddRef( void ) { return InterlockedIncrement(&m_cRef); }
STDMETHODIMP_(ULONG) CCplUiCommandOnPidl::Release( void ) { ASSERT( 0 != m_cRef ); ULONG cRef = InterlockedDecrement(&m_cRef); if ( 0 == cRef ) { delete this; } return cRef; }
STDMETHODIMP CCplUiCommandOnPidl::get_Name( IShellItemArray *psiItemArray, LPWSTR *ppszName ) { UNREFERENCED_PARAMETER(psiItemArray);
HRESULT hr = _GetName(ppszName); return THR(hr); }
STDMETHODIMP CCplUiCommandOnPidl::get_Icon( IShellItemArray *psiItemArray, LPWSTR *ppszIcon ) { UNREFERENCED_PARAMETER(psiItemArray);
HRESULT hr = _GetIconResource(ppszIcon); return THR(hr); }
STDMETHODIMP CCplUiCommandOnPidl::get_Tooltip( IShellItemArray *psiItemArray, LPWSTR *ppszInfotip ) { UNREFERENCED_PARAMETER(psiItemArray);
HRESULT hr = _GetInfotip(ppszInfotip); return THR(hr); }
STDMETHODIMP CCplUiCommandOnPidl::get_CanonicalName( GUID *pguidCommandName ) { UNREFERENCED_PARAMETER(pguidCommandName); return E_NOTIMPL; }
STDMETHODIMP CCplUiCommandOnPidl::get_State( IShellItemArray *psiItemArray, BOOL fOkToBeSlow, UISTATE *puisState ) { ASSERT(NULL != puisState); ASSERT(!IsBadWritePtr(puisState, sizeof(*puisState)));
UNREFERENCED_PARAMETER(psiItemArray); UNREFERENCED_PARAMETER(fOkToBeSlow);
HRESULT hr = S_OK; *puisState = UIS_ENABLED; // default;
//
// We do not handle restrictions on CPL applets in the same
// sense as other 'tasks' in this architecture.
// CPL applets are restricted by the Control Panel folder's
// item enumerator. If the folder enumerates a CPL applet
// then we assume it's valid to present that applet in the
// UI.
//
return THR(hr); }
STDMETHODIMP CCplUiCommandOnPidl::Invoke( IShellItemArray *psiItemArray, IBindCtx *pbc ) { DBG_ENTER(FTF_CPANEL, "CCplUiCommandOnPidl::Invoke");
UNREFERENCED_PARAMETER(psiItemArray); UNREFERENCED_PARAMETER(pbc);
HRESULT hr = _Invoke(NULL, NULL); DBG_EXIT_HRES(FTF_CPANEL, "CCplUiCommandOnPidl::Invoke", hr); return THR(hr); }
//
// ICpUiCommand::Invoke
//
STDMETHODIMP CCplUiCommandOnPidl::Invoke( HWND hwndParent, IUnknown *punkSite ) { DBG_ENTER(FTF_CPANEL, "CCplUiCommandOnPidl::Invoke");
UNREFERENCED_PARAMETER(punkSite);
HRESULT hr = _Invoke(hwndParent, punkSite); DBG_EXIT_HRES(FTF_CPANEL, "CCplUiCommandOnPidl::Invoke", hr); return THR(hr); }
HRESULT CCplUiCommandOnPidl::_Invoke( HWND hwndParent, IUnknown *punkSite ) { DBG_ENTER(FTF_CPANEL, "CCplUiCommandOnPidl::_Invoke");
UNREFERENCED_PARAMETER(hwndParent);
LPITEMIDLIST pidlCpanel; HRESULT hr = SHGetSpecialFolderLocation(NULL, CSIDL_CONTROLS, &pidlCpanel); if (SUCCEEDED(hr)) { LPITEMIDLIST pidl = ILCombine(pidlCpanel, m_pidl); if (FAILED(hr)) { hr = E_OUTOFMEMORY; } else { bool bItemIsBrowsable = false; IUnknown *punkSiteToRelease = NULL; if (NULL == punkSite) { //
// No site provided. Let's use our site.
//
ASSERT(NULL != _punkSite); (punkSite = punkSiteToRelease = _punkSite)->AddRef(); } if (NULL != punkSite) { //
// If we have a site pointer, try to browse the object in-place
// if it is indeed browsable.
//
WCHAR szName[MAX_PATH]; ULONG rgfAttrs = SFGAO_BROWSABLE | SFGAO_FOLDER; hr = SHGetNameAndFlags(pidl, SHGDN_FORPARSING, szName, ARRAYSIZE(szName), &rgfAttrs); if (SUCCEEDED(hr)) { if ((SFGAO_BROWSABLE | SFGAO_FOLDER) & rgfAttrs) { //
// Browse the object in-place. This is the path taken
// by things like the "Printers" folder, "Scheduled Tasks" etc.
//
bItemIsBrowsable = true; IShellBrowser *psb; hr = CPL::ShellBrowserFromSite(punkSite, &psb); if (SUCCEEDED(hr)) { hr = CPL::BrowseIDListInPlace(pidl, psb); psb->Release(); } } } }
if (NULL == punkSite || !bItemIsBrowsable) { //
// Either we don't have a site ptr (can't get to the browser)
// or the item is not browsable. Simply execute it.
// This is the path taken by conventional CPL applets like
// Mouse, Power Options, Display etc.
//
SHELLEXECUTEINFOW sei = { sizeof(sei), // cbSize;
SEE_MASK_INVOKEIDLIST, // fMask
NULL, // hwnd
NULL, // lpVerb
NULL, // lpFile
NULL, // lpParameters
NULL, // lpDirectory
SW_SHOWNORMAL, // nShow
0, // hInstApp
pidl, // lpIDList
NULL, // lpClass
NULL, // hkeyClass
0, // dwHotKey
NULL, // hIcon
NULL // hProcess
}; if (!ShellExecuteExW(&sei)) { hr = ResultFromLastError(); } } ATOMICRELEASE(punkSiteToRelease); ILFree(pidl); } ILFree(pidlCpanel); }
DBG_EXIT_HRES(FTF_CPANEL, "CCplUiCommandOnPidl::_Invoke", hr); return THR(hr); }
HRESULT CCplUiCommandOnPidl::InvokeContextMenu( HWND hwndParent, const POINT *ppt ) { DBG_ENTER(FTF_CPANEL, "CCplUiCommandOnPidl::InvokeContextMenu");
ASSERT(NULL != ppt); ASSERT(NULL == hwndParent || IsWindow(hwndParent));
//
// First build a full pidl to the item.
//
LPITEMIDLIST pidlCpanel; HRESULT hr = SHGetSpecialFolderLocation(hwndParent, CSIDL_CONTROLS, &pidlCpanel); if (SUCCEEDED(hr)) { LPITEMIDLIST pidlFull = ILCombine(pidlCpanel, m_pidl); if (NULL == pidlFull) { hr = E_OUTOFMEMORY; } else { //
// Get the item's context menu interface from the shell.
//
IContextMenu *pcm; hr = SHGetUIObjectFromFullPIDL(pidlFull, hwndParent, IID_PPV_ARG(IContextMenu, &pcm)); if (SUCCEEDED(hr)) { ASSERT(NULL != _punkSite); IContextMenu *pcmNoDelete; hr = Create_ContextMenuWithoutVerbs(pcm, L"cut;delete", IID_PPV_ARG(IContextMenu, &pcmNoDelete)); if (SUCCEEDED(hr)) { hr = IUnknown_DoContextMenuPopup(_punkSite, pcmNoDelete, CMF_NORMAL, *ppt); pcmNoDelete->Release(); } pcm->Release(); } else { TraceMsg(TF_ERROR, "Shell item does not provide a context menu"); } ILFree(pidlFull); } ILFree(pidlCpanel); }
DBG_EXIT_HRES(FTF_CPANEL, "CCplUiCommandOnPidl::InvokeContextMenu", hr); return THR(hr); }
STDMETHODIMP CCplUiCommandOnPidl::GetDataObject( IDataObject **ppdtobj ) { return _GetDataObject(ppdtobj); }
STDMETHODIMP CCplUiCommandOnPidl::LoadIcon( eCPIMGSIZE eSize, HICON *phIcon ) { IShellFolder *psf; HRESULT hr = CPL::GetControlPanelFolder(&psf); if (SUCCEEDED(hr)) { hr = CPL::ExtractIconFromPidl(psf, m_pidl, eSize, phIcon); psf->Release(); } return THR(hr); }
STDMETHODIMP CCplUiCommandOnPidl::LoadName( LPWSTR *ppszName ) { HRESULT hr = _GetName(ppszName); return THR(hr); }
STDMETHODIMP CCplUiCommandOnPidl::LoadTooltip( LPWSTR *ppszTooltip ) { HRESULT hr = _GetInfotip(ppszTooltip); return THR(hr); }
HRESULT CCplUiCommandOnPidl::_Initialize( LPCITEMIDLIST pidl ) { ASSERT(NULL == m_pidl); ASSERT(NULL != pidl);
HRESULT hr = E_OUTOFMEMORY;
m_pidl = ILClone(pidl); if (NULL != m_pidl) { hr = S_OK; } return THR(hr); }
HRESULT CCplUiCommandOnPidl::_GetControlPanelFolder( IShellFolder **ppsf ) { ASSERT(NULL != ppsf); ASSERT(!IsBadWritePtr(ppsf, sizeof(*ppsf)));
HRESULT hr = S_OK;
if (NULL == m_psf) { hr = CPL::GetControlPanelFolder(&m_psf); } *ppsf = m_psf; if (NULL != *ppsf) { (*ppsf)->AddRef(); } return THR(hr); }
HRESULT CCplUiCommandOnPidl::_GetName( LPWSTR *ppszName ) { ASSERT(NULL != m_pidl); ASSERT(NULL != ppszName); ASSERT(!IsBadWritePtr(ppszName, sizeof(*ppszName)));
*ppszName = NULL;
IShellFolder *psf; HRESULT hr = _GetControlPanelFolder(&psf); if (SUCCEEDED(hr)) { STRRET strret; hr = psf->GetDisplayNameOf(m_pidl, SHGDN_INFOLDER, &strret); if (SUCCEEDED(hr)) { hr = StrRetToStrW(&strret, m_pidl, ppszName); } psf->Release(); } return THR(hr); }
HRESULT CCplUiCommandOnPidl::_GetInfotip( LPWSTR *ppszInfotip ) { ASSERT(NULL != ppszInfotip); ASSERT(!IsBadWritePtr(ppszInfotip, sizeof(*ppszInfotip))); ASSERT(NULL != m_pidl);
*ppszInfotip = NULL;
IShellFolder *psf; HRESULT hr = _GetControlPanelFolder(&psf); if (SUCCEEDED(hr)) { IShellFolder2 *psf2; psf->QueryInterface(IID_PPV_ARG(IShellFolder2, &psf2)); if (SUCCEEDED(hr)) { TCHAR szBuf[256]; hr = GetStringProperty(psf2, m_pidl, &SCID_Comment, szBuf, ARRAYSIZE(szBuf)); if (SUCCEEDED(hr)) { hr = SHStrDup(szBuf, ppszInfotip); } psf2->Release(); } psf->Release(); } return THR(hr); }
HRESULT CCplUiCommandOnPidl::_GetIconResource( LPWSTR *ppszIcon ) { ASSERT(NULL != ppszIcon); ASSERT(!IsBadWritePtr(ppszIcon, sizeof(*ppszIcon))); ASSERT(NULL != m_pidl);
LPWSTR pszIconPath = NULL; IShellFolder *psf; HRESULT hr = _GetControlPanelFolder(&psf); if (SUCCEEDED(hr)) { IExtractIconW* pxi; hr = psf->GetUIObjectOf(NULL, 1, (LPCITEMIDLIST *)&m_pidl, IID_PPV_ARG_NULL(IExtractIconW, &pxi)); if (SUCCEEDED(hr)) { WCHAR szPath[MAX_PATH]; int iIndex; UINT wFlags = 0;
hr = pxi->GetIconLocation(GIL_FORSHELL, szPath, ARRAYSIZE(szPath), &iIndex, &wFlags); if (SUCCEEDED(hr)) { const size_t cchIconPath = lstrlenW(szPath) + 15; pszIconPath = (LPWSTR)SHAlloc(cchIconPath * sizeof(WCHAR)); if (pszIconPath) { hr = StringCchPrintfW(pszIconPath, cchIconPath, L"%s,%d", szPath, iIndex); } else { hr = E_OUTOFMEMORY; } } pxi->Release(); } psf->Release(); } *ppszIcon = pszIconPath; return THR(hr); }
HRESULT CCplUiCommandOnPidl::_GetDataObject( IDataObject **ppdtobj ) { ASSERT(NULL != ppdtobj); ASSERT(!IsBadWritePtr(ppdtobj, sizeof(*ppdtobj))); HRESULT hr = S_OK; if (NULL == m_pdtobj) { IShellFolder *psf; hr = _GetControlPanelFolder(&psf); if (SUCCEEDED(hr)) { hr = THR(psf->GetUIObjectOf(NULL, 1, (LPCITEMIDLIST *)&m_pidl, IID_PPV_ARG_NULL(IDataObject, &m_pdtobj))); psf->Release(); } } if (SUCCEEDED(hr)) { ASSERT(NULL != m_pdtobj); (*ppdtobj = m_pdtobj)->AddRef(); } return THR(hr); }
STDMETHODIMP CCplUiCommandOnPidl::GetData( FORMATETC *pFmtEtc, STGMEDIUM *pstm ) { IDataObject *pdtobj; HRESULT hr = _GetDataObject(&pdtobj); if (SUCCEEDED(hr)) { hr = pdtobj->GetData(pFmtEtc, pstm); pdtobj->Release(); } return THR(hr); }
STDMETHODIMP CCplUiCommandOnPidl::GetDataHere( FORMATETC *pFmtEtc, STGMEDIUM *pstm ) { IDataObject *pdtobj; HRESULT hr = _GetDataObject(&pdtobj); if (SUCCEEDED(hr)) { hr = pdtobj->GetDataHere(pFmtEtc, pstm); pdtobj->Release(); } return THR(hr); }
STDMETHODIMP CCplUiCommandOnPidl::QueryGetData( FORMATETC *pFmtEtc ) { IDataObject *pdtobj; HRESULT hr = _GetDataObject(&pdtobj); if (SUCCEEDED(hr)) { hr = pdtobj->QueryGetData(pFmtEtc); pdtobj->Release(); } return THR(hr); }
STDMETHODIMP CCplUiCommandOnPidl::GetCanonicalFormatEtc( FORMATETC *pFmtEtcIn, FORMATETC *pFmtEtcOut ) { IDataObject *pdtobj; HRESULT hr = _GetDataObject(&pdtobj); if (SUCCEEDED(hr)) { hr = pdtobj->GetCanonicalFormatEtc(pFmtEtcIn, pFmtEtcOut); pdtobj->Release(); } return THR(hr); }
STDMETHODIMP CCplUiCommandOnPidl::SetData( FORMATETC *pFmtEtc, STGMEDIUM *pstm, BOOL fRelease ) { IDataObject *pdtobj; HRESULT hr = _GetDataObject(&pdtobj); if (SUCCEEDED(hr)) { hr = pdtobj->SetData(pFmtEtc, pstm, fRelease); pdtobj->Release(); } return THR(hr); }
STDMETHODIMP CCplUiCommandOnPidl::EnumFormatEtc( DWORD dwDirection, LPENUMFORMATETC *ppEnum ) { IDataObject *pdtobj; HRESULT hr = _GetDataObject(&pdtobj); if (SUCCEEDED(hr)) { hr = pdtobj->EnumFormatEtc(dwDirection, ppEnum); pdtobj->Release(); } return THR(hr); }
STDMETHODIMP CCplUiCommandOnPidl::DAdvise( FORMATETC *pFmtEtc, DWORD grfAdv, LPADVISESINK pAdvSink, DWORD *pdwConnection ) { IDataObject *pdtobj; HRESULT hr = _GetDataObject(&pdtobj); if (SUCCEEDED(hr)) { hr = pdtobj->DAdvise(pFmtEtc, grfAdv, pAdvSink, pdwConnection); pdtobj->Release(); } return THR(hr); }
STDMETHODIMP CCplUiCommandOnPidl::DUnadvise( DWORD dwConnection ) { IDataObject *pdtobj; HRESULT hr = _GetDataObject(&pdtobj); if (SUCCEEDED(hr)) { hr = pdtobj->DUnadvise(dwConnection); pdtobj->Release(); } return THR(hr); }
STDMETHODIMP CCplUiCommandOnPidl::EnumDAdvise( LPENUMSTATDATA *ppEnum ) { IDataObject *pdtobj; HRESULT hr = _GetDataObject(&pdtobj); if (SUCCEEDED(hr)) { hr = pdtobj->EnumDAdvise(ppEnum); pdtobj->Release(); } return THR(hr); }
//-----------------------------------------------------------------------------
// Public instance generators.
//-----------------------------------------------------------------------------
HRESULT Create_CplUiElement( LPCWSTR pszName, LPCWSTR pszInfotip, LPCWSTR pszIcon, REFIID riid, void **ppvOut ) { ASSERT(NULL != ppvOut); ASSERT(!IsBadWritePtr(ppvOut, sizeof(*ppvOut)));
return CCplUiElement::CreateInstance(pszName, pszInfotip, pszIcon, riid, ppvOut); }
HRESULT Create_CplUiCommand( LPCWSTR pszName, LPCWSTR pszInfotip, LPCWSTR pszIcon, const IAction *pAction, REFIID riid, void **ppvOut ) { ASSERT(NULL != ppvOut); ASSERT(!IsBadWritePtr(ppvOut, sizeof(*ppvOut)));
return CCplUiCommand::CreateInstance(pszName, pszInfotip, pszIcon, pAction, riid, ppvOut); }
HRESULT Create_CplUiCommandOnPidl( LPCITEMIDLIST pidl, REFIID riid, void **ppvOut ) { ASSERT(NULL != ppvOut); ASSERT(!IsBadWritePtr(ppvOut, sizeof(*ppvOut))); ASSERT(NULL != pidl);
HRESULT hr = CCplUiCommandOnPidl::CreateInstance(pidl, riid, ppvOut); return THR(hr); }
} // namespace CPL
|