windows-nt/Source/XPSP1/NT/ds/security/services/ca/certview/attrib.cpp
2020-09-26 16:20:57 +08:00

519 lines
9.8 KiB
C++

//+--------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1996 - 1999
//
// File: attrib.cpp
//
// Contents: Cert Server Database interface implementation
//
//---------------------------------------------------------------------------
#include <pch.cpp>
#pragma hdrstop
#include <certdb.h>
#include "csdisp.h"
#include "column.h"
#include "attrib.h"
#include "ext.h"
#include "row.h"
#include "view.h"
#if DBG_CERTSRV
LONG g_cCertViewAttribute;
LONG g_cCertViewAttributeTotal;
#endif
CEnumCERTVIEWATTRIBUTE::CEnumCERTVIEWATTRIBUTE()
{
DBGCODE(InterlockedIncrement(&g_cCertViewAttribute));
DBGCODE(InterlockedIncrement(&g_cCertViewAttributeTotal));
m_pvw = NULL;
m_aelt = NULL;
m_cRef = 1;
}
CEnumCERTVIEWATTRIBUTE::~CEnumCERTVIEWATTRIBUTE()
{
DBGCODE(InterlockedDecrement(&g_cCertViewAttribute));
#if DBG_CERTSRV
if (m_cRef > 1)
{
DBGPRINT((
DBG_SS_CERTVIEWI,
"%hs has %d instances left over\n",
"CEnumCERTVIEWATTRIBUTE",
m_cRef));
}
#endif
if (NULL != m_aelt)
{
LocalFree(m_aelt);
m_aelt = NULL;
}
if (NULL != m_pvw)
{
m_pvw->Release();
m_pvw = NULL;
}
}
HRESULT
CEnumCERTVIEWATTRIBUTE::Open(
IN LONG RowId,
IN LONG Flags,
IN ICertView *pvw)
{
HRESULT hr;
if (NULL == pvw)
{
hr = E_POINTER;
_JumpError(hr, error, "NULL parm");
}
m_RowId = RowId;
m_Flags = Flags;
m_pvw = pvw;
m_pvw->AddRef();
if (0 != Flags)
{
hr = E_INVALIDARG;
_JumpError(hr, error, "Flags");
}
hr = Reset();
_JumpIfError2(hr, error, "Reset", S_FALSE);
error:
return(hr);
}
STDMETHODIMP
CEnumCERTVIEWATTRIBUTE::Next(
/* [out, retval] */ LONG *pIndex)
{
HRESULT hr;
DWORD celt;
CERTTRANSBLOB ctbAttributes;
ctbAttributes.pb = NULL;
if (NULL == pIndex)
{
hr = E_POINTER;
_JumpError(hr, error, "NULL parm");
}
*pIndex = -1;
if (m_ieltCurrent + 1 >= m_celtCurrent && !m_fNoMore)
{
hr = ((CCertView *) m_pvw)->EnumAttributesOrExtensions(
m_RowId,
CDBENUM_ATTRIBUTES,
NULL == m_aelt?
NULL :
m_aelt[m_ieltCurrent].pwszName,
CEXT_CHUNK,
&celt,
&ctbAttributes);
if (S_FALSE == hr)
{
m_fNoMore = TRUE;
}
else
{
_JumpIfError(hr, error, "EnumAttributesOrExtensions");
}
hr = _SaveAttributes(celt, &ctbAttributes);
_JumpIfError(hr, error, "_SaveAttributes");
m_ieltCurrent = -1;
m_celtCurrent = celt;
}
if (m_ieltCurrent + 1 >= m_celtCurrent)
{
hr = S_FALSE;
goto error;
}
m_ielt++;
m_ieltCurrent++;
*pIndex = m_ielt;
m_fNoCurrentRecord = FALSE;
hr = S_OK;
error:
if (NULL != ctbAttributes.pb)
{
CoTaskMemFree(ctbAttributes.pb);
}
return(_SetErrorInfo(hr, L"CEnumCERTVIEWATTRIBUTE::Next"));
}
HRESULT
CEnumCERTVIEWATTRIBUTE::_SaveAttributes(
IN DWORD celt,
IN CERTTRANSBLOB const *pctbAttributes)
{
HRESULT hr;
DWORD cbNew;
CERTDBATTRIBUTE *peltNew = NULL;
CERTDBATTRIBUTE *pelt;
CERTTRANSDBATTRIBUTE *ptelt;
CERTTRANSDBATTRIBUTE *pteltEnd;
BYTE *pbNext;
BYTE *pbEnd;
if (NULL == pctbAttributes)
{
hr = E_POINTER;
_JumpError(hr, error, "NULL parm");
}
cbNew = pctbAttributes->cb + celt * (sizeof(*pelt) - sizeof(*ptelt));
peltNew = (CERTDBATTRIBUTE *) LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT, cbNew);
if (NULL == peltNew)
{
hr = E_OUTOFMEMORY;
_JumpError(hr, error, "LocalAlloc");
}
pteltEnd = &((CERTTRANSDBATTRIBUTE *) pctbAttributes->pb)[celt];
if ((BYTE *) pteltEnd > &pctbAttributes->pb[pctbAttributes->cb])
{
hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
_JumpError(hr, error, "bad marshalled data");
}
pelt = peltNew;
pbNext = (BYTE *) &peltNew[celt];
pbEnd = (BYTE *) Add2Ptr(peltNew, cbNew);
for (ptelt = (CERTTRANSDBATTRIBUTE *) pctbAttributes->pb;
ptelt < pteltEnd;
ptelt++, pelt++)
{
hr = CopyMarshalledString(
pctbAttributes,
ptelt->obwszName,
pbEnd,
&pbNext,
&pelt->pwszName);
_JumpIfError(hr, error, "CopyMarshalledString");
hr = CopyMarshalledString(
pctbAttributes,
ptelt->obwszValue,
pbEnd,
&pbNext,
&pelt->pwszValue);
_JumpIfError(hr, error, "CopyMarshalledString");
}
CSASSERT(pbNext == (BYTE *) Add2Ptr(peltNew, cbNew));
if (NULL != m_aelt)
{
LocalFree(m_aelt);
}
m_aelt = peltNew;
peltNew = NULL;
hr = S_OK;
error:
if (NULL != peltNew)
{
LocalFree(peltNew);
}
return(hr);
}
HRESULT
CEnumCERTVIEWATTRIBUTE::_FindAttribute(
OUT CERTDBATTRIBUTE const **ppcda)
{
HRESULT hr;
if (NULL == ppcda)
{
hr = E_POINTER;
_JumpError(hr, error, "NULL parm");
}
if (NULL == m_aelt)
{
hr = E_UNEXPECTED;
_JumpError(hr, error, "NULL m_aelt");
}
if (m_fNoCurrentRecord ||
m_ieltCurrent < 0 ||
m_ieltCurrent >= m_celtCurrent)
{
hr = E_INVALIDARG;
_JumpError(hr, error, "m_fNoCurrentRecord || m_ieltCurrent");
}
*ppcda = &m_aelt[m_ieltCurrent];
hr = S_OK;
error:
return(hr);
}
STDMETHODIMP
CEnumCERTVIEWATTRIBUTE::GetName(
/* [out, retval] */ BSTR *pstrOut)
{
HRESULT hr;
CERTDBATTRIBUTE const *pcda;
if (NULL == pstrOut)
{
hr = E_POINTER;
_JumpError(hr, error, "NULL parm");
}
hr = _FindAttribute(&pcda);
_JumpIfError(hr, error, "_FindAttribute");
if (!ConvertWszToBstr(pstrOut, pcda->pwszName, -1))
{
hr = E_OUTOFMEMORY;
_JumpError(hr, error, "ConvertWszToBstr");
}
error:
return(_SetErrorInfo(hr, L"CEnumCERTVIEWATTRIBUTE::GetName"));
}
STDMETHODIMP
CEnumCERTVIEWATTRIBUTE::GetValue(
/* [out, retval] */ BSTR *pstrOut)
{
HRESULT hr;
CERTDBATTRIBUTE const *pcda;
if (NULL == pstrOut)
{
hr = E_POINTER;
_JumpError(hr, error, "NULL parm");
}
hr = _FindAttribute(&pcda);
_JumpIfError(hr, error, "_FindAttribute");
if (L'\0' == *pcda->pwszValue)
{
hr = CERTSRV_E_PROPERTY_EMPTY;
_JumpError(hr, error, "NULL value");
}
if (!ConvertWszToBstr(pstrOut, pcda->pwszValue, -1))
{
hr = E_OUTOFMEMORY;
_JumpError(hr, error, "ConvertWszToBstr");
}
error:
return(_SetErrorInfo(hr, L"CEnumCERTVIEWATTRIBUTE::GetValue"));
}
STDMETHODIMP
CEnumCERTVIEWATTRIBUTE::Skip(
/* [in] */ LONG celt)
{
HRESULT hr;
LONG ieltnew = m_ielt + celt;
if (-1 > ieltnew)
{
hr = E_INVALIDARG;
_JumpError(hr, error, "Skip back to before start");
}
m_ielt = ieltnew;
m_ieltCurrent += celt;
m_fNoCurrentRecord = TRUE;
hr = S_OK;
error:
return(_SetErrorInfo(hr, L"CEnumCERTVIEWATTRIBUTE::Skip"));
}
STDMETHODIMP
CEnumCERTVIEWATTRIBUTE::Reset(VOID)
{
HRESULT hr;
DWORD celt;
CERTTRANSBLOB ctbAttributes;
ctbAttributes.pb = NULL;
m_fNoMore = FALSE;
hr = ((CCertView *) m_pvw)->EnumAttributesOrExtensions(
m_RowId,
CDBENUM_ATTRIBUTES,
NULL,
CEXT_CHUNK,
&celt,
&ctbAttributes);
if (S_FALSE == hr)
{
m_fNoMore = TRUE;
}
else
{
_JumpIfError(hr, error, "EnumAttributesOrExtensions");
}
hr = _SaveAttributes(celt, &ctbAttributes);
_JumpIfError(hr, error, "_SaveAttributes");
m_ielt = -1;
m_ieltCurrent = -1;
m_celtCurrent = celt;
m_fNoCurrentRecord = TRUE;
error:
if (NULL != ctbAttributes.pb)
{
CoTaskMemFree(ctbAttributes.pb);
}
return(_SetErrorInfo(hr, L"CEnumCERTVIEWATTRIBUTE::Reset"));
}
STDMETHODIMP
CEnumCERTVIEWATTRIBUTE::Clone(
/* [out] */ IEnumCERTVIEWATTRIBUTE **ppenum)
{
HRESULT hr;
IEnumCERTVIEWATTRIBUTE *penum = NULL;
if (NULL == ppenum)
{
hr = E_POINTER;
_JumpError(hr, error, "NULL parm");
}
*ppenum = NULL;
penum = new CEnumCERTVIEWATTRIBUTE;
if (NULL == penum)
{
hr = E_OUTOFMEMORY;
_JumpError(hr, error, "new CEnumCERTVIEWATTRIBUTE");
}
hr = ((CEnumCERTVIEWATTRIBUTE *) penum)->Open(m_RowId, m_Flags, m_pvw);
_JumpIfError(hr, error, "Open");
if (-1 != m_ielt)
{
hr = penum->Skip(m_ielt);
_JumpIfError(hr, error, "Skip");
if (!m_fNoCurrentRecord)
{
LONG Index;
hr = penum->Next(&Index);
_JumpIfError(hr, error, "Next");
CSASSERT(Index == m_ielt);
}
}
*ppenum = penum;
penum = NULL;
hr = S_OK;
error:
if (NULL != penum)
{
penum->Release();
}
return(_SetErrorInfo(hr, L"CEnumCERTVIEWATTRIBUTE::Clone"));
}
HRESULT
CEnumCERTVIEWATTRIBUTE::_SetErrorInfo(
IN HRESULT hrError,
IN WCHAR const *pwszDescription)
{
CSASSERT(FAILED(hrError) || S_OK == hrError || S_FALSE == hrError);
if (FAILED(hrError))
{
HRESULT hr;
hr = DispatchSetErrorInfo(
hrError,
pwszDescription,
wszCLASS_CERTVIEW L".CEnumCERTVIEWATTRIBUTE",
&IID_IEnumCERTVIEWATTRIBUTE);
CSASSERT(hr == hrError);
}
return(hrError);
}
#if 1
// IUnknown implementation
STDMETHODIMP
CEnumCERTVIEWATTRIBUTE::QueryInterface(
const IID& iid,
void **ppv)
{
HRESULT hr;
if (NULL == ppv)
{
hr = E_POINTER;
_JumpError(hr, error, "NULL parm");
}
if (iid == IID_IUnknown)
{
*ppv = static_cast<IEnumCERTVIEWATTRIBUTE *>(this);
}
else if (iid == IID_IDispatch)
{
*ppv = static_cast<IEnumCERTVIEWATTRIBUTE *>(this);
}
else if (iid == IID_IEnumCERTVIEWATTRIBUTE)
{
*ppv = static_cast<IEnumCERTVIEWATTRIBUTE *>(this);
}
else
{
*ppv = NULL;
hr = E_NOINTERFACE;
_JumpError(hr, error, "IID");
}
reinterpret_cast<IUnknown *>(*ppv)->AddRef();
hr = S_OK;
error:
return(hr);
}
ULONG STDMETHODCALLTYPE
CEnumCERTVIEWATTRIBUTE::AddRef()
{
return(InterlockedIncrement(&m_cRef));
}
ULONG STDMETHODCALLTYPE
CEnumCERTVIEWATTRIBUTE::Release()
{
ULONG cRef = InterlockedDecrement(&m_cRef);
if (0 == cRef)
{
delete this;
}
return(cRef);
}
#endif