Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

662 lines
17 KiB

/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Microsoft Windows, Copyright (C) Microsoft Corporation, 2000
File: ExtendedProperty.cpp
Content: Implementation of CExtendedProperty.
History: 06-15-2001 dsie created
------------------------------------------------------------------------------*/
#include "StdAfx.h"
#include "CAPICOM.h"
#include "ExtendedProperty.h"
#include "Convert.h"
#include "Settings.h"
////////////////////////////////////////////////////////////////////////////////
//
// Exported functions.
//
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function : CreateExtendedPropertyObject
Synopsis : Create an IExtendedProperty object.
Parameter: PCCERT_CONTEXT pCertContext - Pointer to CERT_CONTEXT to be used
to initialize the IExtendedProperty
object.
DWORD dwPropId - Property ID.
BOOL bReadOnly - TRUE for read-only, else FALSE.
IExtendedProperty ** ppIExtendedProperty - Pointer to pointer
IExtendedProperty
object.
Remark :
------------------------------------------------------------------------------*/
HRESULT CreateExtendedPropertyObject (PCCERT_CONTEXT pCertContext,
DWORD dwPropId,
BOOL bReadOnly,
IExtendedProperty ** ppIExtendedProperty)
{
HRESULT hr = S_OK;
CComObject<CExtendedProperty> * pCExtendedProperty = NULL;
DebugTrace("Entering CreateExtendedPropertyObject().\n", hr);
//
// Sanity check.
//
ATLASSERT(pCertContext);
ATLASSERT(ppIExtendedProperty);
try
{
//
// Create the object. Note that the ref count will still be 0
// after the object is created.
//
if (FAILED(hr = CComObject<CExtendedProperty>::CreateInstance(&pCExtendedProperty)))
{
DebugTrace("Error [%#x]: CComObject<CExtendedProperty>::CreateInstance() failed.\n", hr);
goto ErrorExit;
}
//
// Initialize object.
//
if (FAILED(hr = pCExtendedProperty->Init(pCertContext, dwPropId, bReadOnly)))
{
DebugTrace("Error [%#x]: pCExtendedProperty->Init() failed.\n", hr);
goto ErrorExit;
}
//
// Return interface pointer to caller.
//
if (FAILED(hr = pCExtendedProperty->QueryInterface(ppIExtendedProperty)))
{
DebugTrace("Error [%#x]: pCExtendedProperty->QueryInterface() failed.\n", hr);
goto ErrorExit;
}
}
catch(...)
{
hr = E_POINTER;
DebugTrace("Exception: invalid parameter.\n");
goto ErrorExit;
}
CommonExit:
DebugTrace("Leaving CreateExtendedPropertyObject().\n");
return hr;
ErrorExit:
//
// Sanity check.
//
ATLASSERT(FAILED(hr));
if (pCExtendedProperty)
{
delete pCExtendedProperty;
}
goto CommonExit;
}
////////////////////////////////////////////////////////////////////////////////
//
// CExtendedProperty
//
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function : CExtendedProperty::get_PropID
Synopsis : Return the prop ID.
Parameter: CAPICOM_PROPID * pVal - Pointer to CAPICOM_PROPID to receive ID.
Remark :
------------------------------------------------------------------------------*/
STDMETHODIMP CExtendedProperty:: get_PropID (CAPICOM_PROPID * pVal)
{
HRESULT hr = S_OK;
DebugTrace("Entering CExtendedProperty::get_PropID().\n");
try
{
//
// Lock access to this object.
//
m_Lock.Lock();
//
// Check parameters.
//
if (NULL == pVal)
{
hr = E_INVALIDARG;
DebugTrace("Error [%#x]: Parameter pVal is NULL.\n", hr);
goto ErrorExit;
}
//
// Return result.
//
*pVal = (CAPICOM_PROPID) m_dwPropId;
}
catch(...)
{
hr = E_POINTER;
DebugTrace("Exception: invalid parameter.\n");
goto ErrorExit;
}
UnlockExit:
//
// Unlock access to this object.
//
m_Lock.Unlock();
DebugTrace("Leaving CExtendedProperty::get_PropID().\n");
return hr;
ErrorExit:
//
// Sanity check.
//
ATLASSERT(FAILED(hr));
ReportError(hr);
goto UnlockExit;
}
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function : CExtendedProperty::put_PropID
Synopsis : Set prop ID.
Parameter: CAPICOM_PROPID newVal - new prop ID.
Remark :
------------------------------------------------------------------------------*/
STDMETHODIMP CExtendedProperty::put_PropID (CAPICOM_PROPID newVal)
{
HRESULT hr = S_OK;
DebugTrace("Entering CExtendedProperty::put_PropID().\n");
try
{
//
// Lock access to this object.
//
m_Lock.Lock();
//
// Make sure it is not read-only.
//
if (m_bReadOnly)
{
hr = CAPICOM_E_NOT_ALLOWED;
DebugTrace("Error [%#x]: Writing read-only PropID property is not allowed.\n", hr);
goto ErrorExit;
}
//
// Don't allow ID change if this is part of a cert. User need to delete
// and then add to the ExtendedProperties collection.
//
if (m_pCertContext)
{
hr = CAPICOM_E_NOT_ALLOWED;
DebugTrace("Error [%#x]: not allowed to change prop ID when the property is attached to a cert.\n", hr);
goto ErrorExit;
}
//
// Free previous blob if available.
//
if (m_DataBlob.pbData)
{
::CoTaskMemFree((LPVOID) m_DataBlob.pbData);
}
//
// Store value.
//
m_dwPropId = newVal;
m_DataBlob.cbData = 0;
m_DataBlob.pbData = NULL;
}
catch(...)
{
hr = E_POINTER;
DebugTrace("Exception: invalid parameter.\n");
goto ErrorExit;
}
UnlockExit:
//
// Unlock access to this object.
//
m_Lock.Unlock();
DebugTrace("Leaving CExtendedProperty::put_PropID().\n");
return hr;
ErrorExit:
//
// Sanity check.
//
ATLASSERT(FAILED(hr));
ReportError(hr);
goto UnlockExit;
}
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function : CExtendedProperty::get_Value
Synopsis : Return the ExtendedProperty data.
Parameter: CAPICOM_ENCODING_TYPE EncodingType - Encoding type.
BSTR * pVal - Pointer to BSTR to receive the data.
Remark :
------------------------------------------------------------------------------*/
STDMETHODIMP CExtendedProperty::get_Value (CAPICOM_ENCODING_TYPE EncodingType,
BSTR * pVal)
{
HRESULT hr = S_OK;
DebugTrace("Entering CExtendedProperty::get_Value().\n");
try
{
//
// Lock access to this object.
//
m_Lock.Lock();
//
// Check parameters.
//
if (NULL == pVal)
{
hr = E_INVALIDARG;
DebugTrace("Error [%#x]: Parameter pVal is NULL.\n", hr);
goto ErrorExit;
}
//
// Make sure Prop ID is valid.
//
if (CAPICOM_PROPID_UNKNOWN == m_dwPropId)
{
hr = CAPICOM_E_PROPERTY_NOT_INITIALIZED;
DebugTrace("Error [%#x]: m_dwPropId member is not initialized.\n", hr);
goto ErrorExit;
}
//
// Return result.
//
if (FAILED(hr = ::ExportData(m_DataBlob, EncodingType, pVal)))
{
DebugTrace("Error [%#x]: ExportData() failed.\n", hr);
goto ErrorExit;
}
}
catch(...)
{
hr = E_POINTER;
DebugTrace("Exception: invalid parameter.\n");
goto ErrorExit;
}
UnlockExit:
//
// Unlock access to this object.
//
m_Lock.Unlock();
DebugTrace("Leaving CExtendedProperty::get_Value().\n");
return hr;
ErrorExit:
//
// Sanity check.
//
ATLASSERT(FAILED(hr));
ReportError(hr);
goto UnlockExit;
}
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function : CExtendedProperty::put_Value
Synopsis : Set the ExtendedProperty data.
Parameter: CAPICOM_ENCODING_TYPE EncodingType - Encoding type.
BSTR newVal - BSTR containing the encoded property.
Remark :
------------------------------------------------------------------------------*/
STDMETHODIMP CExtendedProperty::put_Value (CAPICOM_ENCODING_TYPE EncodingType,
BSTR newVal)
{
HRESULT hr = S_OK;
DATA_BLOB DataBlob = {0, NULL};
DebugTrace("Entering CExtendedProperty::put_Value().\n");
try
{
//
// Lock access to this object.
//
m_Lock.Lock();
//
// Make sure Prop ID is valid.
//
if (CAPICOM_PROPID_UNKNOWN == m_dwPropId)
{
hr = CAPICOM_E_PROPERTY_NOT_INITIALIZED;
DebugTrace("Error [%#x]: m_dwPropId member is not initialized.\n", hr);
goto ErrorExit;
}
//
// Make sure it is not read-only.
//
if (m_bReadOnly)
{
hr = CAPICOM_E_NOT_ALLOWED;
DebugTrace("Error [%#x]: Writing read-only PropID property is not allowed.\n", hr);
goto ErrorExit;
}
//
// Import non-NULL data.
//
if (0 < ::SysStringByteLen(newVal))
{
if (FAILED(hr = ::ImportData(newVal, EncodingType, &DataBlob)))
{
DebugTrace("Error [%#x]: ImportData() failed.\n", hr);
goto ErrorExit;
}
}
//
// Write through to cert, if attached.
//
if (m_pCertContext)
{
LPVOID pvData;
//
// Some properties point to the data directly.
//
if (m_dwPropId == CAPICOM_PROPID_KEY_CONTEXT ||
m_dwPropId == CAPICOM_PROPID_KEY_PROV_HANDLE ||
m_dwPropId == CAPICOM_PROPID_KEY_PROV_INFO ||
m_dwPropId == CAPICOM_PROPID_KEY_SPEC ||
m_dwPropId == CAPICOM_PROPID_DATE_STAMP)
{
pvData = DataBlob.pbData;
}
else if ((m_dwPropId == CAPICOM_PROPID_FRIENDLY_NAME) &&
(L'\0' != newVal[::SysStringLen(newVal) - 1]))
{
LPBYTE pbNewVal = NULL;
if (NULL == (pbNewVal = (LPBYTE) ::CoTaskMemAlloc(DataBlob.cbData + sizeof(WCHAR))))
{
hr = E_OUTOFMEMORY;
DebugTrace("Error [%#x]: CoTaskMemAlloc() failed.\n", hr);
goto ErrorExit;
}
::ZeroMemory(pbNewVal, DataBlob.cbData + sizeof(WCHAR));
::CopyMemory(pbNewVal, DataBlob.pbData, DataBlob.cbData);
::CoTaskMemFree(DataBlob.pbData);
DataBlob.cbData += sizeof(WCHAR);
DataBlob.pbData = pbNewVal;
pvData = &DataBlob;
}
else
{
pvData = &DataBlob;
}
if (!::CertSetCertificateContextProperty(m_pCertContext,
m_dwPropId,
0,
pvData))
{
hr = HRESULT_FROM_WIN32(::GetLastError());
DebugTrace("Error [%#x]: CertSetCertificateContextProperty() failed.\n", hr);
goto ErrorExit;
}
}
//
// Set it.
//
if (m_DataBlob.pbData)
{
::CoTaskMemFree(m_DataBlob.pbData);
}
m_DataBlob = DataBlob;
}
catch(...)
{
hr = E_POINTER;
DebugTrace("Exception: invalid parameter.\n");
goto ErrorExit;
}
UnlockExit:
//
// Unlock access to this object.
//
m_Lock.Unlock();
DebugTrace("Leaving CExtendedProperty::put_Value().\n");
return hr;
ErrorExit:
//
// Sanity check.
//
ATLASSERT(FAILED(hr));
//
// Free resources.
//
if (DataBlob.pbData)
{
::CoTaskMemFree(DataBlob.pbData);
}
ReportError(hr);
goto UnlockExit;
}
////////////////////////////////////////////////////////////////////////////////
//
// Private methods.
//
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function : CExtendedProperty::Init
Synopsis : Initialize the object.
Parameter: PCCERT_CONTEXT pCertContext - Pointer to CERT_CONTEXT to be used
to initialize the IExtendedProperty
object.
DWORD dwPropId - Property ID.
BOOL bReadOnly - TRUE for read-only, else FALSE.
Remark : This method is not part of the COM interface (it is a normal C++
member function). We need it to initialize the object created
internally by us with CERT_ExtendedProperty.
Since it is only a normal C++ member function, this function can
only be called from a C++ class pointer, not an interface pointer.
------------------------------------------------------------------------------*/
STDMETHODIMP CExtendedProperty::Init (PCCERT_CONTEXT pCertContext,
DWORD dwPropId,
BOOL bReadOnly)
{
HRESULT hr = S_OK;
DATA_BLOB DataBlob = {0, NULL};
PCCERT_CONTEXT pCertContext2 = NULL;
DebugTrace("Entering CExtendedProperty::Init().\n");
//
// Sanity check.
//
ATLASSERT(pCertContext);
ATLASSERT(CAPICOM_PROPID_UNKNOWN != dwPropId);
//
// Duplicate the handle.
//
if (!(pCertContext2 = ::CertDuplicateCertificateContext(pCertContext)))
{
hr = HRESULT_FROM_WIN32(::GetLastError());
DebugTrace("Error [%#x]: CertDuplicateCertificateContext() failed.\n", hr);
goto ErrorExit;
}
//
// Get content of property.
//
if (::CertGetCertificateContextProperty(pCertContext,
dwPropId,
NULL,
&DataBlob.cbData))
{
if (NULL == (DataBlob.pbData = (LPBYTE) ::CoTaskMemAlloc(DataBlob.cbData)))
{
hr = E_OUTOFMEMORY;
DebugTrace("Error: out of memory.\n", hr);
goto ErrorExit;
}
if (!::CertGetCertificateContextProperty(pCertContext,
dwPropId,
DataBlob.pbData,
&DataBlob.cbData))
{
hr = HRESULT_FROM_WIN32(::GetLastError());
DebugTrace("Error [%#x]: CertGetCertificateContextProperty() failed.\n", hr);
goto ErrorExit;
}
}
//
// Set states.
//
m_dwPropId = dwPropId;
m_bReadOnly = bReadOnly;
m_DataBlob = DataBlob;
m_pCertContext = pCertContext2;
CommonExit:
DebugTrace("Leaving CExtendedProperty::Init().\n");
return hr;
ErrorExit:
//
// Sanity check.
//
ATLASSERT(FAILED(hr));
//
// Free resources.
//
if (pCertContext2)
{
::CertFreeCertificateContext(pCertContext2);
}
if (DataBlob.pbData)
{
::CoTaskMemFree((LPVOID) DataBlob.pbData);
}
goto CommonExit;
}