Leaked source code of windows server 2003
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.
 
 
 
 
 
 

218 lines
6.4 KiB

#include "precomp.hxx"
#pragma hdrstop
#include <cowsite.h>
#include "contextmenu.h"
// Context Menu Forwarding base class, desinged to delegate
// to a real IContextMenu, and provide inheriting class
// an easy way to override minor bits of functionality
//
CContextMenuForwarder::CContextMenuForwarder(IUnknown* punk) : _cRef(1)
{
_punk = punk;
_punk->AddRef();
_punk->QueryInterface(IID_PPV_ARG(IObjectWithSite, &_pows));
_punk->QueryInterface(IID_PPV_ARG(IContextMenu, &_pcm));
_punk->QueryInterface(IID_PPV_ARG(IContextMenu2, &_pcm2));
_punk->QueryInterface(IID_PPV_ARG(IContextMenu3, &_pcm3));
}
CContextMenuForwarder::~CContextMenuForwarder()
{
if (_pows) _pows->Release();
if (_pcm) _pcm->Release();
if (_pcm2) _pcm2->Release();
if (_pcm3) _pcm3->Release();
_punk->Release();
}
STDMETHODIMP CContextMenuForwarder::QueryInterface(REFIID riid, void **ppv)
{
HRESULT hr = _punk->QueryInterface(riid, ppv);
if (SUCCEEDED(hr))
{
IUnknown* punkTmp = (IUnknown*)(*ppv);
static const QITAB qit[] = {
QITABENT(CContextMenuForwarder, IObjectWithSite), // IID_IObjectWithSite
QITABENT(CContextMenuForwarder, IContextMenu3), // IID_IContextMenu3
QITABENTMULTI(CContextMenuForwarder, IContextMenu2, IContextMenu3), // IID_IContextMenu2
QITABENTMULTI(CContextMenuForwarder, IContextMenu, IContextMenu3), // IID_IContextMenu
{ 0 },
};
HRESULT hrTmp = QISearch(this, qit, riid, ppv);
if (SUCCEEDED(hrTmp))
{
punkTmp->Release();
}
else
{
RIPMSG(FALSE, "CContextMenuForwarder asked for an interface it doesn't support");
*ppv = NULL;
hr = E_NOINTERFACE;
}
}
return hr;
}
STDMETHODIMP_(ULONG) CContextMenuForwarder::AddRef()
{
return InterlockedIncrement(&_cRef);
}
STDMETHODIMP_(ULONG) CContextMenuForwarder::Release()
{
ASSERT( 0 != _cRef );
ULONG cRef = InterlockedDecrement(&_cRef);
if ( 0 == cRef )
{
delete this;
}
return cRef;
}
// Forward everything to the given context menu,
// but remove menu items with the canonical verbs
// given in the semicolon-separated list of canonical verbs
//
class CContextMenuWithoutVerbs : CContextMenuForwarder
{
public:
STDMETHODIMP QueryContextMenu(HMENU hmenu, UINT indexMenu,UINT idCmdFirst,UINT idCmdLast,UINT uFlags);
protected:
CContextMenuWithoutVerbs(IUnknown* punk, LPCWSTR pszVerbList);
friend HRESULT Create_ContextMenuWithoutVerbs(IUnknown* punk, LPCWSTR pszVerbList, REFIID riid, void **ppv);
private:
LPCWSTR _pszVerbList;
};
CContextMenuWithoutVerbs::CContextMenuWithoutVerbs(IUnknown* punk, LPCWSTR pszVerbList) : CContextMenuForwarder(punk)
{
_pszVerbList = pszVerbList; // no reference - this should be a pointer to the code segment
}
HRESULT Create_ContextMenuWithoutVerbs(IUnknown* punk, LPCWSTR pszVerbList, REFIID riid, void **ppv)
{
HRESULT hr = E_OUTOFMEMORY;
*ppv = NULL;
if (pszVerbList)
{
CContextMenuWithoutVerbs* p = new CContextMenuWithoutVerbs(punk, pszVerbList);
if (p)
{
hr = p->QueryInterface(riid, ppv);
p->Release();
}
}
return hr;
}
HRESULT CContextMenuWithoutVerbs::QueryContextMenu(HMENU hmenu, UINT indexMenu,UINT idCmdFirst,UINT idCmdLast,UINT uFlags)
{
HRESULT hr = CContextMenuForwarder::QueryContextMenu(hmenu,indexMenu,idCmdFirst,idCmdLast,uFlags);
if (SUCCEEDED(hr))
{
LPCWSTR pszVerb = _pszVerbList;
while (*pszVerb)
{
WCHAR szVerb[64];
LPCWSTR pszNext = StrChrW(pszVerb, L';');
if (pszNext)
{
size_t cch = (size_t)(pszNext - pszVerb) + 1;
ASSERT(0 < cch && cch < ARRAYSIZE(szVerb)); // we should be large enough for all the canonical verbs we use
StrCpyNW(szVerb, pszVerb, min(cch, ARRAYSIZE(szVerb)));
pszVerb = pszNext + 1;
}
else
{
size_t cch = lstrlenW(pszVerb) + 1;
ASSERT(0 < cch && cch < ARRAYSIZE(szVerb)); // we should be large enough for all the canonical verbs we use
StrCpyNW(szVerb, pszVerb, min(cch, ARRAYSIZE(szVerb)));
pszVerb += cch - 1; // point at NULL
}
ContextMenu_DeleteCommandByName(_pcm, hmenu, idCmdFirst, szVerb);
}
}
return hr;
}
// Forward everything to the given context menu,
// but disable popup menus
//
class CContextMenuWithoutPopups : CContextMenuForwarder
{
public:
STDMETHODIMP QueryContextMenu(HMENU hmenu, UINT indexMenu,UINT idCmdFirst,UINT idCmdLast,UINT uFlags);
protected:
CContextMenuWithoutPopups(IUnknown* punk) : CContextMenuForwarder(punk) {}
friend HRESULT Create_ContextMenuWithoutPopups(IUnknown* punk, REFIID riid, void **ppv);
};
HRESULT Create_ContextMenuWithoutPopups(IUnknown* punk, REFIID riid, void **ppv)
{
HRESULT hr = E_OUTOFMEMORY;
*ppv = NULL;
CContextMenuWithoutPopups* p = new CContextMenuWithoutPopups(punk);
if (p)
{
hr = p->QueryInterface(riid, ppv);
p->Release();
}
return hr;
}
HRESULT CContextMenuWithoutPopups::QueryContextMenu(HMENU hmenu, UINT indexMenu,UINT idCmdFirst,UINT idCmdLast,UINT uFlags)
{
HRESULT hr = CContextMenuForwarder::QueryContextMenu(hmenu,indexMenu,idCmdFirst,idCmdLast,uFlags);
if (SUCCEEDED(hr))
{
MENUITEMINFO mii;
// Disable any submenus that were just added
mii.cbSize = sizeof(mii);
idCmdLast = idCmdFirst + ShortFromResult(hr);
for (UINT i = idCmdFirst; i < idCmdLast; i++)
{
mii.fMask = MIIM_STATE | MIIM_SUBMENU;
if (GetMenuItemInfo(hmenu, i, FALSE, &mii)
&& mii.hSubMenu
&& (mii.fState & (MFS_DISABLED | MFS_GRAYED)) != (MFS_DISABLED | MFS_GRAYED))
{
mii.fMask = MIIM_STATE;
mii.fState |= MFS_DISABLED | MFS_GRAYED;
SetMenuItemInfo(hmenu, i, FALSE, &mii);
}
}
}
return hr;
}