WindowsXP-SP1/admin/snapin/certmgr/dataobj.cpp
2020-09-30 16:53:49 +02:00

814 lines
22 KiB
C++

//+---------------------------------------------------------------------------
//
// 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 <gpedit.h>
#include "compdata.h"
#include "dataobj.h"
#pragma warning(push,3)
#include <sceattch.h>
#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<PBYTE>(&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<PBYTE>(&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<CCookie*> (cookie));
CComObject<CCertMgrDataObject>* pDataObject = 0;
HRESULT hRes = CComObject<CCertMgrDataObject>::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<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 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 <CCertMgrCookie*> (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<CCertMgrDataObject>* pObject;
CComObject<CCertMgrDataObject>::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<BYTE*>(::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<SMMCDataObjects*>(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<MMC_COOKIE>(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;
}