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

428 lines
9.3 KiB
C++

//+--------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1996 - 1999
//
// File: along.cpp
//
// Contents: Cert Server Extension Encoding/Decoding implementation
//
//---------------------------------------------------------------------------
#include "pch.cpp"
#pragma hdrstop
#include <assert.h>
#include "resource.h"
#include "along.h"
#include "celib.h"
//+--------------------------------------------------------------------------
// CCertEncodeLongArray::~CCertEncodeLongArray -- destructor
//
// free memory associated with this instance
//+--------------------------------------------------------------------------
CCertEncodeLongArray::~CCertEncodeLongArray()
{
_Cleanup();
}
//+--------------------------------------------------------------------------
// CCertEncodeLongArray::_Cleanup -- release all resources
//
// free memory associated with this instance
//+--------------------------------------------------------------------------
VOID
CCertEncodeLongArray::_Cleanup()
{
if (NULL != m_aValue)
{
LocalFree(m_aValue);
m_aValue = NULL;
}
m_cValue = 0;
m_cValuesSet = 0;
m_fConstructing = FALSE;
}
//+--------------------------------------------------------------------------
// CCertEncodeLongArray::Decode -- Decode LongArray
//
// Returns S_OK on success.
//+--------------------------------------------------------------------------
STDMETHODIMP
CCertEncodeLongArray::Decode(
/* [in] */ BSTR const strBinary)
{
HRESULT hr = S_OK;
CRYPT_SEQUENCE_OF_ANY *pSequence = NULL;
DWORD cbSequence;
LONG i;
_Cleanup();
if (NULL == strBinary)
{
hr = E_POINTER;
ceERRORPRINTLINE("NULL parm", hr);
goto error;
}
// Decode to an array of ASN blobs:
if (!ceDecodeObject(
X509_ASN_ENCODING,
X509_SEQUENCE_OF_ANY,
(BYTE *) strBinary,
SysStringByteLen(strBinary),
FALSE,
(VOID **) &pSequence,
&cbSequence))
{
hr = ceHLastError();
ceERRORPRINTLINE("ceDecodeObject", hr);
goto error;
}
m_cValue = pSequence->cValue;
m_aValue = (LONG *) LocalAlloc(LMEM_FIXED, m_cValue * sizeof(m_aValue[0]));
if (NULL == m_aValue)
{
hr = E_OUTOFMEMORY;
ceERRORPRINTLINE("LocalAlloc", hr);
goto error;
}
for (i = 0; i < m_cValue; i++)
{
DWORD cb;
// Decode each ASN blob to an integer:
cb = sizeof(m_aValue[i]);
if (!CryptDecodeObject(
X509_ASN_ENCODING,
X509_INTEGER,
pSequence->rgValue[i].pbData,
pSequence->rgValue[i].cbData,
0, // dwFlags
(VOID *) &m_aValue[i],
&cb))
{
hr = ceHLastError();
ceERRORPRINTLINE("CryptDecodeObject", hr);
goto error;
}
assert(sizeof(m_aValue[i]) == cb);
}
error:
if (NULL != pSequence)
{
LocalFree(pSequence);
}
if (S_OK != hr)
{
_Cleanup();
}
return(_SetErrorInfo(hr, L"CCertEncodeLongArray::Decode"));
}
//+--------------------------------------------------------------------------
// CCertEncodeLongArray::GetCount -- Get Array count
//
// Returns S_OK on success.
//+--------------------------------------------------------------------------
STDMETHODIMP
CCertEncodeLongArray::GetCount(
/* [out, retval] */ LONG __RPC_FAR *pCount)
{
HRESULT hr = S_OK;
if (NULL == pCount)
{
hr = E_POINTER;
ceERRORPRINTLINE("NULL parm", hr);
goto error;
}
if (NULL == m_aValue)
{
hr = E_INVALIDARG;
ceERRORPRINTLINE("bad parameter", hr);
goto error;
}
*pCount = m_cValue;
error:
return(_SetErrorInfo(hr, L"CCertEncodeLongArray::GetCount"));
}
//+--------------------------------------------------------------------------
// CCertEncodeLongArray::GetValue -- Fetch the indexed long
//
// Returns S_OK on success.
//+--------------------------------------------------------------------------
STDMETHODIMP
CCertEncodeLongArray::GetValue(
/* [in] */ LONG Index,
/* [out, retval] */ LONG __RPC_FAR *pValue)
{
HRESULT hr = S_OK;
BYTE *pb;
if (NULL == pValue)
{
hr = E_POINTER;
ceERRORPRINTLINE("NULL parm", hr);
goto error;
}
if (NULL == m_aValue || Index >= m_cValue)
{
hr = E_INVALIDARG;
ceERRORPRINTLINE("bad parameter", hr);
goto error;
}
// Bitmap only exists when constrcuting!
if (m_fConstructing)
{
pb = (BYTE *) &m_aValue[m_cValue];
if (!GETBIT(pb, Index))
{
hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
ceERRORPRINTLINE("uninitialized", hr);
goto error;
}
}
*pValue = m_aValue[Index];
error:
return(_SetErrorInfo(hr, L"CCertEncodeLongArray::GetValue"));
}
//+--------------------------------------------------------------------------
// CCertEncodeLongArray::Reset -- clear out data, and set up to encode new data
//
// Returns S_OK on success.
//+--------------------------------------------------------------------------
STDMETHODIMP
CCertEncodeLongArray::Reset(
/* [in] */ LONG Count)
{
HRESULT hr = S_OK;
DWORD cbAlloc;
_Cleanup();
m_fConstructing = TRUE;
if (CENCODEMAX < Count || 0 > Count)
{
hr = E_INVALIDARG;
ceERRORPRINTLINE("bad count parameter", hr);
goto error;
}
cbAlloc = Count * sizeof(m_aValue[0]) + BITSTOBYTES(Count);
m_aValue = (LONG *) LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT, cbAlloc);
if (NULL == m_aValue)
{
hr = E_OUTOFMEMORY;
ceERRORPRINTLINE("LocalAlloc", hr);
goto error;
}
m_cValue = Count;
error:
return(_SetErrorInfo(hr, L"CCertEncodeLongArray::Reset"));
}
//+--------------------------------------------------------------------------
// CCertEncodeLongArray::SetValue -- Set an array long
//
// Returns S_OK on success.
//+--------------------------------------------------------------------------
STDMETHODIMP
CCertEncodeLongArray::SetValue(
/* [in] */ LONG Index,
/* [in] */ LONG Value)
{
HRESULT hr = S_OK;
BYTE *pb;
if (!m_fConstructing ||
NULL == m_aValue ||
Index >= m_cValue ||
m_cValuesSet >= m_cValue)
{
hr = E_INVALIDARG;
ceERRORPRINTLINE("bad parameter", hr);
goto error;
}
pb = (BYTE *) &m_aValue[m_cValue];
if (GETBIT(pb, Index))
{
hr = E_INVALIDARG;
ceERRORPRINTLINE("already set", hr);
goto error;
}
SETBIT(pb, Index);
m_aValue[Index] = Value;
m_cValuesSet++;
error:
return(_SetErrorInfo(hr, L"CCertEncodeLongArray::SetValue"));
}
//+--------------------------------------------------------------------------
// CCertEncodeLongArray::Encode -- Encode LongArray
//
// Returns S_OK on success.
//+--------------------------------------------------------------------------
STDMETHODIMP
CCertEncodeLongArray::Encode(
/* [out, retval] */ BSTR __RPC_FAR *pstrBinary)
{
HRESULT hr = S_OK;
LONG i;
CRYPT_SEQUENCE_OF_ANY Sequence;
BYTE *pbEncoded = NULL;
DWORD cbEncoded;
Sequence.cValue = 0;
Sequence.rgValue = NULL;
if (NULL == pstrBinary)
{
hr = E_POINTER;
ceERRORPRINTLINE("NULL parm", hr);
goto error;
}
ceFreeBstr(pstrBinary);
if (!m_fConstructing || NULL == m_aValue)
{
hr = E_INVALIDARG;
ceERRORPRINTLINE("bad parameter", hr);
goto error;
}
if (m_cValuesSet != m_cValue)
{
hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
ceERRORPRINTLINE("m_cValuesSet", hr);
goto error;
}
Sequence.rgValue = (CRYPT_DER_BLOB *) LocalAlloc(
LMEM_FIXED,
m_cValue * sizeof(Sequence.rgValue[0]));
if (NULL == Sequence.rgValue)
{
hr = E_OUTOFMEMORY;
ceERRORPRINTLINE("LocalAlloc", hr);
goto error;
}
for (i = 0; i < m_cValue; i++)
{
// Encode each integer into an ASN blob:
if (!ceEncodeObject(
X509_ASN_ENCODING,
X509_INTEGER,
&m_aValue[i],
0,
FALSE,
&Sequence.rgValue[i].pbData,
&Sequence.rgValue[i].cbData))
{
hr = ceHLastError();
ceERRORPRINTLINE("ceEncodeObject", hr);
goto error;
}
Sequence.cValue++;
}
assert((LONG) Sequence.cValue == m_cValue);
// Encode each integer into an ASN blob:
if (!ceEncodeObject(
X509_ASN_ENCODING,
X509_SEQUENCE_OF_ANY,
&Sequence,
0,
FALSE,
&pbEncoded,
&cbEncoded))
{
hr = ceHLastError();
ceERRORPRINTLINE("ceEncodeObject", hr);
goto error;
}
if (!ceConvertWszToBstr(
pstrBinary,
(WCHAR const *) pbEncoded,
cbEncoded))
{
hr = E_OUTOFMEMORY;
ceERRORPRINTLINE("ceConvertWszToBstr", hr);
goto error;
}
error:
if (NULL != pbEncoded)
{
LocalFree(pbEncoded);
}
if (NULL != Sequence.rgValue)
{
assert((LONG) Sequence.cValue <= m_cValue);
for (i = 0; i < (LONG) Sequence.cValue; i++)
{
assert(NULL != Sequence.rgValue[i].pbData);
LocalFree(Sequence.rgValue[i].pbData);
}
LocalFree(Sequence.rgValue);
}
return(_SetErrorInfo(hr, L"CCertEncodeLongArray::Encode"));
}
//+--------------------------------------------------------------------------
// CCertEncodeLongArray::_SetErrorInfo -- set error object information
//
// Returns passed HRESULT
//+--------------------------------------------------------------------------
HRESULT
CCertEncodeLongArray::_SetErrorInfo(
IN HRESULT hrError,
IN WCHAR const *pwszDescription)
{
assert(FAILED(hrError) || S_OK == hrError || S_FALSE == hrError);
if (FAILED(hrError))
{
HRESULT hr;
hr = ceDispatchSetErrorInfo(
hrError,
pwszDescription,
wszCLASS_CERTENCODELONGARRAY,
&IID_ICertEncodeLongArray);
assert(hr == hrError);
}
return(hrError);
}