428 lines
9.3 KiB
C++
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);
|
|
}
|