|
|
//==============================================================;
//
// This source code is only intended as a supplement to existing Microsoft documentation.
//
//
//
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
// PURPOSE.
//
// Copyright (C) 1999 Microsoft Corporation. All Rights Reserved.
//
//
//
//==============================================================;
#include "CMenuExt.h"
#include "globals.h"
#include "resource.h"
#include <crtdbg.h>
// we need to do this to get around MMC.IDL - it explicitly defines
// the clipboard formats as WCHAR types...
#define _T_CCF_DISPLAY_NAME _T("CCF_DISPLAY_NAME")
#define _T_CCF_NODETYPE _T("CCF_NODETYPE")
#define _T_CCF_SNAPIN_CLASSID _T("CCF_SNAPIN_CLASSID")
// These are the clipboard formats that we must supply at a minimum.
// mmc.h actually defined these. We can make up our own to use for
// other reasons. We don't need any others at this time.
UINT CContextMenuExtension::s_cfDisplayName = RegisterClipboardFormat(_T_CCF_DISPLAY_NAME); UINT CContextMenuExtension::s_cfNodeType = RegisterClipboardFormat(_T_CCF_NODETYPE); UINT CContextMenuExtension::s_cfSnapInCLSID = RegisterClipboardFormat(_T_CCF_SNAPIN_CLASSID);
CContextMenuExtension::CContextMenuExtension() : m_cref(0) { OBJECT_CREATED }
CContextMenuExtension::~CContextMenuExtension() { OBJECT_DESTROYED }
///////////////////////
// IUnknown implementation
///////////////////////
STDMETHODIMP CContextMenuExtension::QueryInterface(REFIID riid, LPVOID *ppv) { if (!ppv) return E_FAIL; *ppv = NULL; if (IsEqualIID(riid, IID_IUnknown)) *ppv = static_cast<IExtendContextMenu *>(this); else if (IsEqualIID(riid, IID_IExtendContextMenu)) *ppv = static_cast<IExtendContextMenu *>(this); if (*ppv) { reinterpret_cast<IUnknown *>(*ppv)->AddRef(); return S_OK; } return E_NOINTERFACE; }
STDMETHODIMP_(ULONG) CContextMenuExtension::AddRef() { return InterlockedIncrement((LONG *)&m_cref); }
STDMETHODIMP_(ULONG) CContextMenuExtension::Release() { if (InterlockedDecrement((LONG *)&m_cref) == 0) { // we need to decrement our object count in the DLL
delete this; return 0; } return m_cref; }
HRESULT CContextMenuExtension::ExtractData( IDataObject* piDataObject, CLIPFORMAT cfClipFormat, BYTE* pbData, DWORD cbData ) { HRESULT hr = S_OK; FORMATETC formatetc = {cfClipFormat, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL}; STGMEDIUM stgmedium = {TYMED_HGLOBAL, NULL}; stgmedium.hGlobal = ::GlobalAlloc(GPTR, cbData); do // false loop
{ if (NULL == stgmedium.hGlobal) { hr = E_OUTOFMEMORY; break; } hr = piDataObject->GetDataHere( &formatetc, &stgmedium ); if ( FAILED(hr) ) { break; } BYTE* pbNewData = reinterpret_cast<BYTE*>(stgmedium.hGlobal); if (NULL == pbNewData) { hr = E_UNEXPECTED; break; } ::memcpy( pbData, pbNewData, cbData ); } while (FALSE); // false loop
if (NULL != stgmedium.hGlobal) { ::GlobalFree(stgmedium.hGlobal); } return hr; } // ExtractData()
HRESULT CContextMenuExtension::ExtractString( IDataObject *piDataObject, CLIPFORMAT cfClipFormat, WCHAR *pstr, DWORD cchMaxLength) { return ExtractData( piDataObject, cfClipFormat, (PBYTE)pstr, cchMaxLength ); }
HRESULT CContextMenuExtension::ExtractSnapInCLSID( IDataObject* piDataObject, CLSID* pclsidSnapin ) { return ExtractData( piDataObject, s_cfSnapInCLSID, (PBYTE)pclsidSnapin, sizeof(CLSID) ); }
HRESULT CContextMenuExtension::ExtractObjectTypeGUID( IDataObject* piDataObject, GUID* pguidObjectType ) { return ExtractData( piDataObject, s_cfNodeType, (PBYTE)pguidObjectType, sizeof(GUID) ); }
///////////////////////////////
// Interface IExtendContextMenu
///////////////////////////////
HRESULT CContextMenuExtension::AddMenuItems( /* [in] */ LPDATAOBJECT piDataObject, /* [in] */ LPCONTEXTMENUCALLBACK piCallback, /* [out][in] */ long __RPC_FAR *pInsertionAllowed) { HRESULT hr = S_OK; CONTEXTMENUITEM menuItemsTask[] = { { L"People Extension", L"Do an extension thing", 1, CCM_INSERTIONPOINTID_3RDPARTY_TASK , 0, 0 }, { NULL, NULL, 0, 0, 0 } }; // Loop through and add each of the menu items
if (*pInsertionAllowed & CCM_INSERTIONALLOWED_TASK) { for (CONTEXTMENUITEM *m = menuItemsTask; m->strName; m++) { hr = piCallback->AddItem(m); if (FAILED(hr)) break; } } return hr; }
HRESULT CContextMenuExtension::Command( /* [in] */ long lCommandID, /* [in] */ LPDATAOBJECT piDataObject) { WCHAR pszName[255]; HRESULT hr = ExtractString(piDataObject, s_cfDisplayName, pszName, sizeof(pszName)); MAKE_TSTRPTR_FROMWIDE(ptrname, pszName); if (SUCCEEDED(hr)) { switch (lCommandID) { case 1: ::MessageBox(NULL, ptrname, _T("Menu Command"), MB_OK|MB_ICONEXCLAMATION); break; } } return hr; }
|