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.
573 lines
16 KiB
573 lines
16 KiB
//+---------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1997-2002.
|
|
//
|
|
// 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;
|
|
// security review 2/21/2002 BryanWal ok
|
|
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;
|
|
// security review 2/21/2002 BryanWal ok
|
|
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);
|
|
}
|
|
|
|
if ( SUCCEEDED (hr) )
|
|
{
|
|
CComObject<CCertTemplatesDataObject>* pObject;
|
|
hr = CComObject<CCertTemplatesDataObject>::CreateInstance(&pObject);
|
|
ASSERT(SUCCEEDED (hr) && pObject != NULL);
|
|
if ( SUCCEEDED (hr) )
|
|
{
|
|
if ( pObject )
|
|
{
|
|
// 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()];
|
|
if ( pGuid )
|
|
{
|
|
// security review 2/21/2002 BryanWal ok
|
|
CopyMemory(pGuid, rgGuids.GetData(), cb);
|
|
pObject->SetMultiSelData((BYTE*)pGuid, cb);
|
|
for (int i=0; i < rgCookiesSelected.GetSize(); ++i)
|
|
{
|
|
pObject->AddCookie(rgCookiesSelected[i]);
|
|
}
|
|
|
|
hr = pObject->QueryInterface(
|
|
IID_PPV_ARG (IDataObject, ppDataObject));
|
|
}
|
|
else
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
else
|
|
hr = E_FAIL;
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
//+--------------------------------------------------------------------------
|
|
//
|
|
// 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);
|
|
// security review 2/21/2002 BryanWal ok
|
|
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;
|
|
|
|
// security review 2/21/2002 BryanWal ok
|
|
wcsncpy((LPWSTR)((BYTE *)pDSObj + (pDSObj->aObjects[0].offsetName)),
|
|
(LPCWSTR) adsiPath, cbPath);
|
|
|
|
// security review 2/21/2002 BryanWal ok
|
|
wcsncpy((LPWSTR)((BYTE *)pDSObj + (pDSObj->aObjects[0].offsetClass)),
|
|
(LPCWSTR) pCertTemplate->GetClass (), cbClass);
|
|
|
|
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;
|
|
}
|
|
|