windows-nt/Source/XPSP1/NT/admin/snapin/certentp/dataobj.cpp
2020-09-26 16:20:57 +08:00

551 lines
14 KiB
C++

//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1997-2001.
//
// File: DataObj.cpp
//
// Contents: Implementation of data object classes: CCertTemplatesDataObject
//
//----------------------------------------------------------------------------
#include "stdafx.h"
USE_HANDLE_MACROS("CERTTMPL(dataobj.cpp)")
#include "compdata.h"
#include "dataobj.h"
#include "uuids.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#include "stddtobj.cpp"
// IDataObject interface implementation
CCertTemplatesDataObject::CCertTemplatesDataObject()
: m_pCookie (0),
m_objecttype (CERTTMPL_SNAPIN),
m_dataobjecttype (CCT_UNINITIALIZED),
m_pbMultiSelData(NULL),
m_cbMultiSelData(0),
m_bMultiSelDobj(false),
m_iCurr(0)
{
}
HRESULT CCertTemplatesDataObject::GetDataHere(
FORMATETC __RPC_FAR *pFormatEtcIn,
STGMEDIUM __RPC_FAR *pMedium)
{
const CLIPFORMAT cf=pFormatEtcIn->cfFormat;
if (cf == m_CFNodeType)
{
if ( IsValidObjectType (m_pCookie->m_objecttype) )
{
const GUID* pguid = GetObjectTypeGUID( m_pCookie->m_objecttype );
stream_ptr s(pMedium);
return s.Write(pguid, sizeof(GUID));
}
else
return E_UNEXPECTED;
}
else if (cf == m_CFSnapInCLSID)
{
stream_ptr s(pMedium);
return s.Write(&m_SnapInCLSID, sizeof(GUID));
}
else if (cf == m_CFNodeTypeString)
{
if ( IsValidObjectType (m_pCookie->m_objecttype) )
{
const BSTR strGUID = GetObjectTypeString( m_pCookie->m_objecttype );
stream_ptr s(pMedium);
return s.Write(strGUID);
}
else
return E_UNEXPECTED;
}
else if (cf == m_CFDisplayName)
{
return PutDisplayName(pMedium);
}
else if (cf == m_CFDataObjectType)
{
stream_ptr s(pMedium);
return s.Write(&m_dataobjecttype, sizeof(m_dataobjecttype));
}
else if (cf == m_CFRawCookie)
{
stream_ptr s(pMedium);
if ( m_pCookie )
{
// CODEWORK This cast ensures that the data format is
// always a CCookie*, even for derived subclasses
if ( ((CCertTmplCookie*) MMC_MULTI_SELECT_COOKIE) == m_pCookie ||
IsValidObjectType (m_pCookie->m_objecttype) )
{
CCookie* pcookie = (CCookie*) m_pCookie;
return s.Write(reinterpret_cast<PBYTE>(&pcookie), sizeof(m_pCookie));
}
else
return E_UNEXPECTED;
}
}
else if ( cf == m_CFMultiSel )
{
return CreateMultiSelectObject (pMedium);
}
else if (cf == m_CFSnapinPreloads)
{
stream_ptr s(pMedium);
// If this is TRUE, then the next time this snapin is loaded, it will
// be preloaded to give us the opportunity to change the root node
// name before the user sees it.
BOOL x = 1;
return s.Write (reinterpret_cast<PBYTE>(&x), sizeof (BOOL));
}
return DV_E_FORMATETC;
}
HRESULT CCertTemplatesDataObject::Initialize(
CCertTmplCookie* pcookie,
DATA_OBJECT_TYPES type,
CCertTmplComponentData& refComponentData)
{
if ( !pcookie || m_pCookie )
{
ASSERT(FALSE);
return S_OK; // Initialize must not fail
}
m_dataobjecttype = type;
m_pCookie = pcookie;
if ( ((CCertTmplCookie*) MMC_MULTI_SELECT_COOKIE) != m_pCookie )
((CRefcountedObject*)m_pCookie)->AddRef();
VERIFY( SUCCEEDED(refComponentData.GetClassID(&m_SnapInCLSID)) );
return S_OK;
}
CCertTemplatesDataObject::~CCertTemplatesDataObject()
{
if ( ((CCertTmplCookie*) MMC_MULTI_SELECT_COOKIE) != m_pCookie &&
m_pCookie && IsValidObjectType (m_pCookie->m_objecttype) )
{
((CRefcountedObject*)m_pCookie)->Release();
}
if (m_pbMultiSelData)
delete m_pbMultiSelData;
for (int i=0; i < m_rgCookies.GetSize(); ++i)
{
m_rgCookies[i]->Release();
m_rgCookies[i] = 0;
}
}
void CCertTemplatesDataObject::AddCookie(CCertTmplCookie* pCookie)
{
m_rgCookies.Add(pCookie);
pCookie->AddRef();
}
HRESULT CCertTemplatesDataObject::PutDisplayName(STGMEDIUM* pMedium)
// Writes the "friendly name" to the provided storage medium
// Returns the result of the write operation
{
AFX_MANAGE_STATE (AfxGetStaticModuleState ());
CString strDomainName = m_pCookie->GetManagedDomainDNSName();
stream_ptr s (pMedium);
CString snapinName;
snapinName.FormatMessage (IDS_CERTTMPL_ROOT_NODE_NAME, strDomainName);
return s.Write ((PCWSTR) snapinName);
}
// Register the clipboard formats
CLIPFORMAT CCertTemplatesDataObject::m_CFDisplayName =
(CLIPFORMAT)RegisterClipboardFormat(CCF_DISPLAY_NAME);
CLIPFORMAT CDataObject::m_CFRawCookie =
(CLIPFORMAT)RegisterClipboardFormat(L"CERTTMPL_SNAPIN_RAW_COOKIE");
CLIPFORMAT CCertTemplatesDataObject::m_CFMultiSel =
(CLIPFORMAT)RegisterClipboardFormat(CCF_OBJECT_TYPES_IN_MULTI_SELECT);
CLIPFORMAT CCertTemplatesDataObject::m_CFMultiSelDobj =
(CLIPFORMAT)RegisterClipboardFormat(CCF_MMC_MULTISELECT_DATAOBJECT);
CLIPFORMAT CCertTemplatesDataObject::m_CFMultiSelDataObjs =
(CLIPFORMAT)RegisterClipboardFormat(CCF_MULTI_SELECT_SNAPINS);
CLIPFORMAT CCertTemplatesDataObject::m_CFDsObjectNames =
(CLIPFORMAT)RegisterClipboardFormat(CFSTR_DSOBJECTNAMES);
void CCertTemplatesDataObject::SetMultiSelData(BYTE* pbMultiSelData, UINT cbMultiSelData)
{
m_pbMultiSelData = pbMultiSelData;
m_cbMultiSelData = cbMultiSelData;
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CCertTmplComponentData::QueryDataObject (
MMC_COOKIE cookie,
DATA_OBJECT_TYPES type,
LPDATAOBJECT* ppDataObject)
{
if ( MMC_MULTI_SELECT_COOKIE == cookie )
{
return QueryMultiSelectDataObject (cookie, type, ppDataObject);
}
CCertTmplCookie* pUseThisCookie =
(CCertTmplCookie*) ActiveBaseCookie (
reinterpret_cast<CCookie*> (cookie));
CComObject<CCertTemplatesDataObject>* pDataObject = 0;
HRESULT hRes = CComObject<CCertTemplatesDataObject>::CreateInstance(&pDataObject);
if ( FAILED(hRes) )
return hRes;
HRESULT hr = pDataObject->Initialize (
pUseThisCookie,
type,
*this);
if ( FAILED(hr) )
{
delete pDataObject;
return hr;
}
pDataObject->AddRef();
*ppDataObject = pDataObject;
return hr;
}
typedef CArray<GUID, const GUID&> CGUIDArray;
void GuidArray_Add(CGUIDArray& rgGuids, const GUID& guid)
{
for (INT_PTR i=rgGuids.GetUpperBound(); i >= 0; --i)
{
if (rgGuids[i] == guid)
break;
}
if (i < 0)
rgGuids.Add(guid);
}
HRESULT CCertTmplComponentData::QueryMultiSelectDataObject(MMC_COOKIE cookie, DATA_OBJECT_TYPES type,
LPDATAOBJECT* ppDataObject)
{
ASSERT(ppDataObject != NULL);
if (ppDataObject == NULL)
return E_POINTER;
HRESULT hr = S_OK;
CGUIDArray rgGuids;
// Determine the items selected
ASSERT(m_pResultData != NULL);
RESULTDATAITEM rdi;
ZeroMemory(&rdi, sizeof(rdi));
rdi.mask = RDI_STATE;
rdi.nIndex = -1;
rdi.nState = TVIS_SELECTED;
CCookiePtrArray rgCookiesSelected;
while (m_pResultData->GetNextItem (&rdi) == S_OK)
{
const GUID* pguid;
CCertTmplCookie* pCookie = reinterpret_cast <CCertTmplCookie*> (rdi.lParam);
if ( pCookie )
{
rgCookiesSelected.Add (pCookie);
switch (pCookie->m_objecttype)
{
case CERTTMPL_CERT_TEMPLATE:
pguid = &NODEID_CertTmpl_CERT_TEMPLATE;
break;
default:
ASSERT (0);
continue;
}
}
else
{
hr = E_INVALIDARG;
break;
}
GuidArray_Add(rgGuids, *pguid);
}
CComObject<CCertTemplatesDataObject>* pObject;
CComObject<CCertTemplatesDataObject>::CreateInstance(&pObject);
ASSERT(pObject != NULL);
// Save cookie and type for delayed rendering
pObject->Initialize ((CCertTmplCookie*) cookie,
type,
*this);
pObject->SetMultiSelDobj();
// Store the coclass with the data object
UINT cb = (UINT)(rgGuids.GetSize() * sizeof(GUID));
GUID* pGuid = new GUID[(UINT)rgGuids.GetSize()];
CopyMemory(pGuid, rgGuids.GetData(), cb);
pObject->SetMultiSelData((BYTE*)pGuid, cb);
for (int i=0; i < rgCookiesSelected.GetSize(); ++i)
{
pObject->AddCookie(rgCookiesSelected[i]);
}
return pObject->QueryInterface(
IID_PPV_ARG (IDataObject, ppDataObject));
}
//+--------------------------------------------------------------------------
//
// Member: CDataObject::Create
//
// Synopsis: Fill the hGlobal in [lpmedium] with the data in pBuffer
//
// Arguments: [pBuffer] - [in] the data to be written
// [len] - [in] the length of that data
// [pMedium] - [in,out] where to store the data
// History:
//
//---------------------------------------------------------------------------
HRESULT CCertTemplatesDataObject::Create (const void* pBuffer, int len, LPSTGMEDIUM pMedium)
{
HRESULT hr = DV_E_TYMED;
//
// Do some simple validation
//
if (pBuffer == NULL || pMedium == NULL)
return E_POINTER;
//
// Make sure the type medium is HGLOBAL
//
if (pMedium->tymed == TYMED_HGLOBAL) {
//
// Create the stream on the hGlobal passed in
//
LPSTREAM lpStream = 0;
hr = CreateStreamOnHGlobal(pMedium->hGlobal, FALSE, &lpStream);
ASSERT (SUCCEEDED (hr));
if (SUCCEEDED(hr))
{
//
// Write to the stream the number of bytes
//
ULONG written = 0;
hr = lpStream->Write(pBuffer, len, &written);
ASSERT (SUCCEEDED (hr));
//
// Because we told CreateStreamOnHGlobal with 'FALSE',
// only the stream is released here.
// Note - the caller (i.e. snap-in, object) will free the HGLOBAL
// at the correct time. This is according to the IDataObject specification.
//
lpStream->Release();
}
}
return hr;
}
//+----------------------------------------------------------------------------
//
// Method: CCertTemplatesDataObject::CreateMultiSelectObject
//
// Synopsis: this is to create the list of types selected
//
//-----------------------------------------------------------------------------
HRESULT CCertTemplatesDataObject::CreateMultiSelectObject(LPSTGMEDIUM pMedium)
{
ASSERT(m_pbMultiSelData != 0);
ASSERT(m_cbMultiSelData != 0);
pMedium->tymed = TYMED_HGLOBAL;
pMedium->hGlobal = ::GlobalAlloc(GMEM_SHARE|GMEM_MOVEABLE,
(m_cbMultiSelData + sizeof(DWORD)));
if (pMedium->hGlobal == NULL)
return STG_E_MEDIUMFULL;
BYTE* pb = reinterpret_cast<BYTE*>(::GlobalLock(pMedium->hGlobal));
*((DWORD*)pb) = m_cbMultiSelData / sizeof(GUID);
pb += sizeof(DWORD);
CopyMemory(pb, m_pbMultiSelData, m_cbMultiSelData);
::GlobalUnlock(pMedium->hGlobal);
return S_OK;
}
LPDATAOBJECT ExtractMultiSelect (LPDATAOBJECT lpDataObject)
{
if (lpDataObject == NULL)
return NULL;
SMMCDataObjects * pDO = NULL;
STGMEDIUM stgmedium = { TYMED_HGLOBAL, NULL };
FORMATETC formatetc = { CCertTemplatesDataObject::m_CFMultiSelDataObjs, NULL,
DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
if ( FAILED (lpDataObject->GetData (&formatetc, &stgmedium)) )
{
return NULL;
}
else
{
pDO = reinterpret_cast<SMMCDataObjects*>(stgmedium.hGlobal);
return pDO->lpDataObject[0]; //assume that ours is the 1st
}
}
STDMETHODIMP CCertTemplatesDataObject::GetData(LPFORMATETC lpFormatetc, LPSTGMEDIUM pMedium)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
HRESULT hr = DV_E_CLIPFORMAT;
if (lpFormatetc->cfFormat == m_CFMultiSel)
{
ASSERT(((CCertTmplCookie*) MMC_MULTI_SELECT_COOKIE) == m_pCookie);
if ( ((CCertTmplCookie*) MMC_MULTI_SELECT_COOKIE) != m_pCookie )
return E_FAIL;
hr = CreateMultiSelectObject (pMedium);
}
else if ( lpFormatetc->cfFormat == m_CFDsObjectNames )
{
switch (m_pCookie->m_objecttype)
{
case CERTTMPL_CERT_TEMPLATE:
{
CCertTemplate* pCertTemplate = dynamic_cast <CCertTemplate*> (m_pCookie);
ASSERT (pCertTemplate);
if ( pCertTemplate )
{
// figure out how much storage we need
CString adsiPath;
adsiPath = pCertTemplate->GetLDAPPath ();
int cbPath = sizeof (WCHAR) * (adsiPath.GetLength() + 1);
int cbClass = sizeof (WCHAR) * (pCertTemplate->GetClass ().GetLength() + 1);;
int cbStruct = sizeof(DSOBJECTNAMES); //contains already a DSOBJECT embedded struct
LPDSOBJECTNAMES pDSObj = 0;
pDSObj = (LPDSOBJECTNAMES)GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT,
cbStruct + cbPath + cbClass);
if ( pDSObj )
{
// write the info
pDSObj->clsidNamespace = CLSID_CertTemplatesSnapin;
pDSObj->cItems = 1;
pDSObj->aObjects[0].dwFlags = 0;
pDSObj->aObjects[0].dwProviderFlags = 0;
pDSObj->aObjects[0].offsetName = cbStruct;
pDSObj->aObjects[0].offsetClass = cbStruct + cbPath;
wcscpy((LPWSTR)((BYTE *)pDSObj + (pDSObj->aObjects[0].offsetName)),
(LPCWSTR) adsiPath);
wcscpy((LPWSTR)((BYTE *)pDSObj + (pDSObj->aObjects[0].offsetClass)),
(LPCWSTR) pCertTemplate->GetClass ());
pMedium->hGlobal = (HGLOBAL)pDSObj;
pMedium->tymed = TYMED_HGLOBAL;
pMedium->pUnkForRelease = NULL;
hr = S_OK;
}
else
hr = STG_E_MEDIUMFULL;
}
}
break;
default:
break;
}
}
return hr;
}
STDMETHODIMP CCertTemplatesDataObject::Next(ULONG celt, MMC_COOKIE* rgelt, ULONG *pceltFetched)
{
HRESULT hr = S_OK;
if ((rgelt == NULL) ||
((celt > 1) && (pceltFetched == NULL)))
{
hr = E_INVALIDARG;
return hr;
}
ULONG celtTemp = (ULONG)(m_rgCookies.GetSize() - m_iCurr);
celtTemp = (celt < celtTemp) ? celt : celtTemp;
if (pceltFetched)
*pceltFetched = celtTemp;
if (celtTemp == 0)
return S_FALSE;
for (ULONG i=0; i < celtTemp; ++i)
{
rgelt[i] = reinterpret_cast<MMC_COOKIE>(m_rgCookies[m_iCurr++]);
}
return (celtTemp < celt) ? S_FALSE : S_OK;
}
STDMETHODIMP CCertTemplatesDataObject::Skip(ULONG celt)
{
ULONG celtTemp = (ULONG)(m_rgCookies.GetSize() - m_iCurr);
celtTemp = (celt < celtTemp) ? celt : celtTemp;
m_iCurr += celtTemp;
return (celtTemp < celt) ? S_FALSE : S_OK;
}
STDMETHODIMP CCertTemplatesDataObject::Reset(void)
{
m_iCurr = 0;
return S_OK;
}