//+--------------------------------------------------------------------------- // // 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(&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(&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 (cookie)); CComObject* pDataObject = 0; HRESULT hRes = CComObject::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 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 (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* pObject; CComObject::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(::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(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 (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(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; }