|
|
//==============================================================;
//
// 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 "DataObj.h"
#include "guids.h"
#include "DeleBase.h"
#include "Space.h"
//
// This is the minimum set of clipboard formats we must implement.
// MMC uses these to get necessary information from our snapin about
// our nodes.
//
// 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_SZNODETYPE _T("CCF_SZNODETYPE")
#define _T_CCF_SNAPIN_CLASSID _T("CCF_SNAPIN_CLASSID")
#define _T_CCF_OBJECT_TYPES_IN_MULTI_SELECT _T("CCF_OBJECT_TYPES_IN_MULTI_SELECT")
#define _T_CCF_INTERNAL_SNAPIN _T("{2479DB32-5276-11d2-94F5-00C04FB92EC2}")
// 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 CDataObject::s_cfDisplayName = RegisterClipboardFormat(_T_CCF_DISPLAY_NAME); UINT CDataObject::s_cfNodeType = RegisterClipboardFormat(_T_CCF_NODETYPE); UINT CDataObject::s_cfSZNodeType = RegisterClipboardFormat(_T_CCF_SZNODETYPE); UINT CDataObject::s_cfSnapinClsid = RegisterClipboardFormat(_T_CCF_SNAPIN_CLASSID); UINT CDataObject::s_cfInternal = RegisterClipboardFormat(_T_CCF_INTERNAL_SNAPIN);
//We must also supply a data object for CCF_OBJECT_TYPES_IN_MULTI_SELECT
UINT CDataObject::s_cfMultiSelect = RegisterClipboardFormat(_T_CCF_OBJECT_TYPES_IN_MULTI_SELECT);
CDataObject::CDataObject(MMC_COOKIE cookie, DATA_OBJECT_TYPES context) : m_lCookie(cookie), m_context(context), m_cref(0) { //Do the following if the data object is a multiselection data object
if ( MMC_MULTI_SELECT_COOKIE == m_lCookie ) {
pCookies = new MMC_COOKIE[MAX_COOKIES];
for (int n = 0; n < MAX_COOKIES; n++) { pCookies[n] = NULL; } } }
CDataObject::~CDataObject() { //Do the following if the data object is a multiselection data object
if ( MMC_MULTI_SELECT_COOKIE == m_lCookie ) delete [] pCookies; }
///////////////////////
// IUnknown implementation
///////////////////////
STDMETHODIMP CDataObject::QueryInterface(REFIID riid, LPVOID *ppv) { if (!ppv) return E_FAIL;
*ppv = NULL;
if (IsEqualIID(riid, IID_IUnknown)) *ppv = static_cast<IDataObject *>(this); else if (IsEqualIID(riid, IID_IDataObject)) *ppv = static_cast<IDataObject *>(this);
if (*ppv) { reinterpret_cast<IUnknown *>(*ppv)->AddRef(); return S_OK; }
return E_NOINTERFACE; }
STDMETHODIMP_(ULONG) CDataObject::AddRef() { return InterlockedIncrement((LONG *)&m_cref); }
STDMETHODIMP_(ULONG) CDataObject::Release() { if (InterlockedDecrement((LONG *)&m_cref) == 0) { delete this; return 0; } return m_cref;
}
/////////////////////////////////////////////////////////////////////////////
// IDataObject implementation
//
HRESULT CDataObject::GetDataHere( FORMATETC *pFormatEtc, // [in] Pointer to the FORMATETC structure
STGMEDIUM *pMedium // [out] Pointer to the STGMEDIUM structure
) { const CLIPFORMAT cf = pFormatEtc->cfFormat; IStream *pStream = NULL;
CDelegationBase *base = GetBaseNodeObject();
HRESULT hr = CreateStreamOnHGlobal( pMedium->hGlobal, FALSE, &pStream ); if ( FAILED(hr) ) return hr; // Minimal error checking
hr = DV_E_FORMATETC; // Unknown format
if (cf == s_cfDisplayName) { const _TCHAR *pszName = base->GetDisplayName();
MAKE_WIDEPTR_FROMTSTR(wszName, pszName);
// get length of original string and convert it accordingly
ULONG ulSizeofName = lstrlen(pszName); ulSizeofName++; // Count null character
ulSizeofName *= sizeof(WCHAR);
hr = pStream->Write(wszName, ulSizeofName, NULL); } else if (cf == s_cfNodeType) { const GUID *pGUID = (const GUID *)&base->getNodeType();
hr = pStream->Write(pGUID, sizeof(GUID), NULL); } else if (cf == s_cfSZNodeType) { LPOLESTR szGuid; hr = StringFromCLSID(base->getNodeType(), &szGuid);
if (SUCCEEDED(hr)) { hr = pStream->Write(szGuid, wcslen(szGuid), NULL); CoTaskMemFree(szGuid); } } else if (cf == s_cfSnapinClsid) { const GUID *pGUID = NULL; pGUID = &CLSID_CComponentData;
hr = pStream->Write(pGUID, sizeof(GUID), NULL); } else if (cf == s_cfInternal) { // we are being asked to get our this pointer from the IDataObject interface
// only our own snap-in objects will know how to do this.
CDataObject *pThis = this; hr = pStream->Write( &pThis, sizeof(CDataObject*), NULL ); }
pStream->Release();
return hr; }
HRESULT CDataObject::GetData (LPFORMATETC lpFormatetcIn, LPSTGMEDIUM lpMedium)
{ HRESULT hr = S_FALSE;
const CLIPFORMAT cf = lpFormatetcIn->cfFormat;
CDelegationBase *base = GetBaseNodeObject();
if (cf == s_cfMultiSelect) { // MMC requires support for this format to load any extensions
// that extend the selected result items
BYTE byData[256] = {0}; SMMCObjectTypes* pData = reinterpret_cast<SMMCObjectTypes*>(byData);
//We need the node type GUID of the selected items.
//from CRocket::thisGuid
GUID guid = { 0x29743811, 0x4c4b, 0x11d2, { 0x89, 0xd8, 0x0, 0x0, 0x21, 0x47, 0x31, 0x28 } }; //Enter data required for the SMMCObjectTypes structure
//count specifies the number of unique node types in the multiselection
//Here, all CRocket items are of the same node type, so count == 1.
pData->count = 1; pData->guid[0] = guid;
// Calculate the size of SMMCObjectTypes.
int cb = sizeof(GUID)*(pData->count) + sizeof (SMMCObjectTypes); //Fill out parameters
lpMedium->tymed = TYMED_HGLOBAL; lpMedium->hGlobal = ::GlobalAlloc(GMEM_SHARE|GMEM_MOVEABLE, cb); if (lpMedium->hGlobal == NULL) return STG_E_MEDIUMFULL;
BYTE* pb = reinterpret_cast<BYTE*>(::GlobalLock(lpMedium->hGlobal)); CopyMemory(pb, pData, cb); ::GlobalUnlock(lpMedium->hGlobal);
hr = S_OK;
}
return hr; }
/////////////////////////////////////////////////////////////////////////////
// Global helper functions to help work with dataobjects and
// clipboard formats
//---------------------------------------------------------------------------
// Returns the current object based on the s_cfInternal clipboard format
//
CDataObject* GetOurDataObject ( LPDATAOBJECT lpDataObject // [in] IComponent pointer
) { HRESULT hr = S_OK; CDataObject *pSDO = NULL;
// check to see if the data object is a special data object.
if ( IS_SPECIAL_DATAOBJECT (lpDataObject) ) { //Code for handling a special data object goes here.
//Note that the MMC SDK samples do not handle
//special data objects, so we exit if we get one.
return NULL; }
STGMEDIUM stgmedium = { TYMED_HGLOBAL, NULL }; FORMATETC formatetc = { CDataObject::s_cfInternal, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
// Allocate memory for the stream
stgmedium.hGlobal = GlobalAlloc( GMEM_SHARE, sizeof(CDataObject *));
if (!stgmedium.hGlobal) { hr = E_OUTOFMEMORY; }
if SUCCEEDED(hr) // Attempt to get data from the object
hr = lpDataObject->GetDataHere( &formatetc, &stgmedium );
// stgmedium now has the data we need
if (SUCCEEDED(hr)) { pSDO = *(CDataObject **)(stgmedium.hGlobal); }
// if we have memory free it
if (stgmedium.hGlobal) GlobalFree(stgmedium.hGlobal);
return pSDO;
} // end GetOurDataObject()
|