//+--------------------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1997-2001. // // File: DataObj.cpp // // Contents: Implementation of data object classes // //---------------------------------------------------------------------------- #include "stdafx.h" USE_HANDLE_MACROS("CERTMGR(dataobj.cpp)") #include #include "compdata.h" #include "dataobj.h" #pragma warning(push,3) #include #pragma warning(pop) #include "uuids.h" #ifdef _DEBUG #ifndef ALPHA #define new DEBUG_NEW #endif #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif #include "stddtobj.cpp" // IDataObject interface implementation CCertMgrDataObject::CCertMgrDataObject() : m_pCookie (0), m_objecttype (CERTMGR_SNAPIN), m_dataobjecttype (CCT_UNINITIALIZED), m_dwLocation (0), m_pGPEInformation (0), m_pRSOPInformation (0), m_pbMultiSelData(NULL), m_cbMultiSelData(0), m_bMultiSelDobj(false), m_iCurr(0) { } HRESULT CCertMgrDataObject::GetDataHere( FORMATETC __RPC_FAR *pFormatEtcIn, STGMEDIUM __RPC_FAR *pMedium) { HRESULT hr = DV_E_FORMATETC; 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); hr = s.Write(pguid, sizeof(GUID)); } else hr = E_UNEXPECTED; } else if (cf == m_CFSnapInCLSID) { stream_ptr s(pMedium); hr = 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); hr = s.Write(strGUID); } else hr = E_UNEXPECTED; } else if (cf == m_CFDisplayName) { hr = PutDisplayName(pMedium); } else if (cf == m_CFDataObjectType) { stream_ptr s(pMedium); hr = s.Write(&m_dataobjecttype, sizeof(m_dataobjecttype)); } else if (cf == m_CFMachineName) { if ( IsValidObjectType (m_pCookie->m_objecttype) ) { stream_ptr s(pMedium); hr = s.Write(m_pCookie->QueryNonNULLMachineName()); } else hr = E_UNEXPECTED; } 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 ( ((CCertMgrCookie*) MMC_MULTI_SELECT_COOKIE) == m_pCookie || IsValidObjectType (m_pCookie->m_objecttype) ) { CCookie* pcookie = (CCookie*) m_pCookie; hr = s.Write(reinterpret_cast(&pcookie), sizeof(m_pCookie)); } else hr = E_UNEXPECTED; } } else if ( cf == m_CFSCE_GPTUnknown ) { hr = CreateGPTUnknown (pMedium); } else if ( cf == m_CFSCE_RSOPUnknown ) { hr = CreateRSOPUnknown (pMedium); } else if ( cf == m_CFMultiSel ) { hr = 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. hr = s.Write (reinterpret_cast(&m_fAllowOverrideMachineName), sizeof (BOOL)); } return hr; } HRESULT CCertMgrDataObject::Initialize( CCertMgrCookie* pcookie, DATA_OBJECT_TYPES type, BOOL fAllowOverrideMachineName, DWORD dwLocation, CString szManagedUser, CString szManagedComputer, CString szManagedService, CCertMgrComponentData& refComponentData) { if ( !pcookie || m_pCookie ) { ASSERT(FALSE); return S_OK; // Initialize must not fail } m_dataobjecttype = type; m_pCookie = pcookie; m_fAllowOverrideMachineName = fAllowOverrideMachineName; m_dwLocation = dwLocation; m_szManagedUser = szManagedUser; m_szManagedComputer = szManagedComputer; m_szManagedService = szManagedService; if ( ((CCertMgrCookie*) MMC_MULTI_SELECT_COOKIE) != m_pCookie ) ((CRefcountedObject*)m_pCookie)->AddRef(); VERIFY( SUCCEEDED(refComponentData.GetClassID(&m_SnapInCLSID)) ); return S_OK; } CCertMgrDataObject::~CCertMgrDataObject() { if ( m_pGPEInformation ) { m_pGPEInformation->Release (); m_pGPEInformation = 0; } if ( m_pRSOPInformation ) { m_pRSOPInformation->Release (); m_pRSOPInformation = 0; } if ( ((CCertMgrCookie*) 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(); } } void CCertMgrDataObject::AddCookie(CCertMgrCookie* pCookie) { m_rgCookies.Add(pCookie); pCookie->AddRef(); } HRESULT CCertMgrDataObject::PutDisplayName(STGMEDIUM* pMedium) // Writes the "friendly name" to the provided storage medium // Returns the result of the write operation { AFX_MANAGE_STATE (AfxGetStaticModuleState ()); CString strDisplayName = m_pCookie->QueryTargetServer(); CString formattedName; switch (m_dwLocation) { case CERT_SYSTEM_STORE_CURRENT_USER: VERIFY (formattedName.LoadString (IDS_SCOPE_SNAPIN_TITLE_USER)); break; case CERT_SYSTEM_STORE_LOCAL_MACHINE: if (strDisplayName.IsEmpty()) { VERIFY (formattedName.LoadString (IDS_SCOPE_SNAPIN_TITLE_LOCAL_MACHINE)); } else formattedName.FormatMessage (IDS_SCOPE_SNAPIN_TITLE_MACHINE, strDisplayName); break; case CERT_SYSTEM_STORE_CURRENT_SERVICE: case CERT_SYSTEM_STORE_SERVICES: if (strDisplayName.IsEmpty()) { // Get this machine name and add it to the string. formattedName.FormatMessage (IDS_SCOPE_SNAPIN_TITLE_SERVICE_LOCAL_MACHINE, m_szManagedService); } else { formattedName.FormatMessage (IDS_SCOPE_SNAPIN_TITLE_SERVICE, m_szManagedService, strDisplayName); } break; // These next two titles can only be set from the debugger. They are used // to create custom .MSC files. case -1: formattedName.FormatMessage (IDS_SCOPE_SNAPIN_TITLE_CERT_MGR_CURRENT_USER); break; case 0: formattedName.FormatMessage (IDS_SCOPE_SNAPIN_TITLE_FILE); break; default: ASSERT (0); break; } stream_ptr s (pMedium); return s.Write (formattedName); } // Register the clipboard formats CLIPFORMAT CCertMgrDataObject::m_CFDisplayName = (CLIPFORMAT)RegisterClipboardFormat(CCF_DISPLAY_NAME); CLIPFORMAT CCertMgrDataObject::m_CFMachineName = (CLIPFORMAT)RegisterClipboardFormat(L"MMC_SNAPIN_MACHINE_NAME"); CLIPFORMAT CDataObject::m_CFRawCookie = (CLIPFORMAT)RegisterClipboardFormat(L"CERTMGR_SNAPIN_RAW_COOKIE"); CLIPFORMAT CCertMgrDataObject::m_CFMultiSel = (CLIPFORMAT)RegisterClipboardFormat(CCF_OBJECT_TYPES_IN_MULTI_SELECT); CLIPFORMAT CCertMgrDataObject::m_CFMultiSelDobj = (CLIPFORMAT)RegisterClipboardFormat(CCF_MMC_MULTISELECT_DATAOBJECT); CLIPFORMAT CCertMgrDataObject::m_CFSCEModeType = (CLIPFORMAT)RegisterClipboardFormat(CCF_SCE_MODE_TYPE); CLIPFORMAT CCertMgrDataObject::m_CFSCE_GPTUnknown = (CLIPFORMAT)RegisterClipboardFormat(CCF_SCE_GPT_UNKNOWN); CLIPFORMAT CCertMgrDataObject::m_CFSCE_RSOPUnknown = (CLIPFORMAT)RegisterClipboardFormat(CCF_SCE_RSOP_UNKNOWN); CLIPFORMAT CCertMgrDataObject::m_CFMultiSelDataObjs = (CLIPFORMAT)RegisterClipboardFormat(CCF_MULTI_SELECT_SNAPINS); void CCertMgrDataObject::SetMultiSelData(BYTE* pbMultiSelData, UINT cbMultiSelData) { m_pbMultiSelData = pbMultiSelData; m_cbMultiSelData = cbMultiSelData; } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// STDMETHODIMP CCertMgrComponentData::QueryDataObject ( MMC_COOKIE cookie, DATA_OBJECT_TYPES type, LPDATAOBJECT* ppDataObject) { if ( MMC_MULTI_SELECT_COOKIE == cookie ) { return QueryMultiSelectDataObject (cookie, type, ppDataObject); } CCertMgrCookie* pUseThisCookie = (CCertMgrCookie*) ActiveBaseCookie ( reinterpret_cast (cookie)); CComObject* pDataObject = 0; HRESULT hRes = CComObject::CreateInstance(&pDataObject); if ( FAILED(hRes) ) return hRes; if ( m_szManagedUser.IsEmpty () ) m_szManagedUser = m_szLoggedInUser; m_szManagedComputer = pUseThisCookie->QueryTargetServer(); if ( m_szManagedComputer.IsEmpty () && m_strMachineNamePersist.CompareNoCase (m_szThisComputer) ) // != { m_szManagedComputer = m_strMachineNamePersist; } if ( m_szManagedComputer.IsEmpty () ) m_szManagedComputer = pUseThisCookie->QueryNonNULLMachineName (); if ( m_szManagedComputer.IsEmpty () ) m_szManagedComputer = m_szThisComputer; // Raid bug 278491 US: Cert search for a remote computer application // fails to search certs on a remote computer, instead running a search // on Local machine if ( m_szManagedComputer.CompareNoCase (m_szThisComputer) ) pUseThisCookie->SetMachineName (m_szManagedComputer); // Truncate leading "\\" if ( !wcsncmp (m_szManagedComputer, L"\\\\", 2) ) m_szManagedComputer = m_szManagedComputer.Mid (2); HRESULT hr = pDataObject->Initialize ( pUseThisCookie, type, m_fAllowOverrideMachineName, m_dwLocationPersist, m_szManagedUser, m_szManagedComputer, m_szManagedServiceDisplayName, *this); if ( FAILED(hr) ) { delete pDataObject; return hr; } if ( m_pGPEInformation ) pDataObject->SetGPTInformation (m_pGPEInformation); if ( m_bIsRSOP ) { IRSOPInformation* pRSOPInformation = 0; switch (pUseThisCookie->m_objecttype) { case CERTMGR_CERT_POLICIES_COMPUTER: case CERTMGR_PKP_AUTOENROLLMENT_COMPUTER_SETTINGS: case CERTMGR_SAFER_COMPUTER_ROOT: case CERTMGR_SAFER_COMPUTER_LEVELS: case CERTMGR_SAFER_COMPUTER_ENTRIES: case CERTMGR_SAFER_COMPUTER_LEVEL: case CERTMGR_SAFER_COMPUTER_ENTRY: case CERTMGR_SAFER_COMPUTER_TRUSTED_PUBLISHERS: case CERTMGR_SAFER_COMPUTER_DEFINED_FILE_TYPES: pRSOPInformation = m_pRSOPInformationComputer; break; case CERTMGR_CERT_POLICIES_USER: case CERTMGR_PKP_AUTOENROLLMENT_USER_SETTINGS: case CERTMGR_SAFER_USER_ROOT: case CERTMGR_SAFER_USER_LEVELS: case CERTMGR_SAFER_USER_ENTRIES: case CERTMGR_SAFER_USER_LEVEL: case CERTMGR_SAFER_USER_ENTRY: case CERTMGR_SAFER_USER_TRUSTED_PUBLISHERS: case CERTMGR_SAFER_USER_DEFINED_FILE_TYPES: case CERTMGR_SAFER_COMPUTER_ENFORCEMENT: case CERTMGR_SAFER_USER_ENFORCEMENT: pRSOPInformation = m_pRSOPInformationUser; break; case CERTMGR_CERTIFICATE: case CERTMGR_LOG_STORE: case CERTMGR_PHYS_STORE: case CERTMGR_USAGE: case CERTMGR_CRL_CONTAINER: case CERTMGR_CTL_CONTAINER: case CERTMGR_CERT_CONTAINER: case CERTMGR_CRL: case CERTMGR_CTL: case CERTMGR_AUTO_CERT_REQUEST: case CERTMGR_LOG_STORE_GPE: case CERTMGR_LOG_STORE_RSOP: default: pRSOPInformation = m_pRSOPInformationComputer; break; } pDataObject->SetRSOPInformation (pRSOPInformation); } 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 CCertMgrComponentData::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; CCertMgrCookie* pCookie = reinterpret_cast (rdi.lParam); if ( pCookie ) { rgCookiesSelected.Add (pCookie); switch (pCookie->m_objecttype) { case CERTMGR_CERTIFICATE: pguid = &NODEID_CertMgr_CERTIFICATE; break; case CERTMGR_CTL: pguid = &NODEID_CertMgr_CTL; break; case CERTMGR_CRL: pguid = &NODEID_CertMgr_CRL; break; case CERTMGR_AUTO_CERT_REQUEST: pguid = &NODEID_CertMgr_AUTOCERT; break; case CERTMGR_SAFER_COMPUTER_ENTRY: pguid = &NODEID_Safer_COMPUTER_ENTRY; break; case CERTMGR_SAFER_USER_ENTRY: pguid = &NODEID_Safer_USER_ENTRY; 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 ((CCertMgrCookie*) cookie, type, m_fAllowOverrideMachineName, m_dwLocationPersist, m_szManagedUser, m_szManagedComputer, m_szManagedServiceDisplayName, *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 ) { 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)); } else return E_OUTOFMEMORY; } HRESULT CCertMgrDataObject::SetGPTInformation(IGPEInformation * pGPTInformation) { HRESULT hr = S_OK; if ( pGPTInformation ) { m_pGPEInformation = pGPTInformation; m_pGPEInformation->AddRef (); } else hr = E_POINTER; return hr; } HRESULT CCertMgrDataObject::SetRSOPInformation(IRSOPInformation * pRSOPInformation) { HRESULT hr = S_OK; if ( pRSOPInformation ) { m_pRSOPInformation = pRSOPInformation; m_pRSOPInformation->AddRef (); } else hr = E_POINTER; return hr; } //+-------------------------------------------------------------------------- // // Member: CDataObject::CreateGPTUnknown // // Synopsis: Fill the hGlobal in [lpMedium] with a pointer to GPT's // IUnknown interface. The object requesting this will be // responsible for Releasing the interface // // History: // //--------------------------------------------------------------------------- HRESULT CCertMgrDataObject::CreateGPTUnknown(LPSTGMEDIUM lpMedium) { HRESULT hr = S_OK; LPUNKNOWN pUnk = 0; if ( !m_pGPEInformation ) { // // If we don't have a pointer to a GPT interface then we must not // be in a mode where we're extending GPT and we can't provide a // pointer to its IUnknown // return E_UNEXPECTED; } hr = m_pGPEInformation->QueryInterface ( IID_PPV_ARG (IUnknown, &pUnk)); if ( SUCCEEDED(hr) ) { return Create (&pUnk, sizeof(pUnk), lpMedium); } else { return hr; } } //+-------------------------------------------------------------------------- // // Member: CDataObject::CreateRSOPUnknown // // Synopsis: Fill the hGlobal in [lpMedium] with a pointer to RSOP's // IUnknown interface. The object requesting this will be // responsible for Releasing the interface // // History: // //--------------------------------------------------------------------------- HRESULT CCertMgrDataObject::CreateRSOPUnknown(LPSTGMEDIUM lpMedium) { HRESULT hr = S_OK; LPUNKNOWN pUnk = 0; if ( !m_pRSOPInformation ) { // // If we don't have a pointer to a GPT interface then we must not // be in a mode where we're extending GPT and we can't provide a // pointer to its IUnknown // return E_UNEXPECTED; } hr = m_pRSOPInformation->QueryInterface ( IID_PPV_ARG (IUnknown, &pUnk)); if ( SUCCEEDED(hr) ) { return Create (&pUnk, sizeof(pUnk), lpMedium); } else { 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 // [lpMedium] - [in,out] where to store the data // History: // //--------------------------------------------------------------------------- HRESULT CCertMgrDataObject::Create (const void* pBuffer, int len, LPSTGMEDIUM lpMedium) { HRESULT hr = DV_E_TYMED; // // Do some simple validation // if (pBuffer == NULL || lpMedium == NULL) return E_POINTER; // // Make sure the type medium is HGLOBAL // if (lpMedium->tymed == TYMED_HGLOBAL) { // // Create the stream on the hGlobal passed in // LPSTREAM lpStream = 0; hr = CreateStreamOnHGlobal(lpMedium->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: CCertMgrDataObject::CreateMultiSelectObject // // Synopsis: this is to create the list of types selected // //----------------------------------------------------------------------------- HRESULT CCertMgrDataObject::CreateMultiSelectObject(LPSTGMEDIUM lpMedium) { ASSERT(m_pbMultiSelData != 0); ASSERT(m_cbMultiSelData != 0); lpMedium->tymed = TYMED_HGLOBAL; lpMedium->hGlobal = ::GlobalAlloc(GMEM_SHARE|GMEM_MOVEABLE, (m_cbMultiSelData + sizeof(DWORD))); if (lpMedium->hGlobal == NULL) return STG_E_MEDIUMFULL; BYTE* pb = reinterpret_cast(::GlobalLock(lpMedium->hGlobal)); *((DWORD*)pb) = m_cbMultiSelData / sizeof(GUID); pb += sizeof(DWORD); CopyMemory(pb, m_pbMultiSelData, m_cbMultiSelData); ::GlobalUnlock(lpMedium->hGlobal); return S_OK; } LPDATAOBJECT ExtractMultiSelect (LPDATAOBJECT lpDataObject) { if (lpDataObject == NULL) return NULL; SMMCDataObjects * pDO = NULL; STGMEDIUM stgmedium = { TYMED_HGLOBAL, NULL }; FORMATETC formatetc = { CCertMgrDataObject::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 CCertMgrDataObject::GetData(LPFORMATETC lpFormatetc, LPSTGMEDIUM lpMedium) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); HRESULT hr = DV_E_CLIPFORMAT; if (lpFormatetc->cfFormat == m_CFMultiSel) { ASSERT(((CCertMgrCookie*) MMC_MULTI_SELECT_COOKIE) == m_pCookie); if ( ((CCertMgrCookie*) MMC_MULTI_SELECT_COOKIE) == m_pCookie ) { hr = CreateMultiSelectObject (lpMedium); } else hr = E_FAIL; } return hr; } STDMETHODIMP CCertMgrDataObject::Next(ULONG celt, MMC_COOKIE* rgelt, ULONG *pceltFetched) { HRESULT hr = S_OK; if ((rgelt == NULL) || ((celt > 1) && (pceltFetched == NULL))) { hr = E_INVALIDARG; CHECK_HRESULT(hr); 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 CCertMgrDataObject::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 CCertMgrDataObject::Reset(void) { m_iCurr = 0; return S_OK; }