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.
567 lines
17 KiB
567 lines
17 KiB
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Copyright (C) Microsoft Corporation
|
|
//
|
|
// Module Name:
|
|
//
|
|
// IASAttrList.cpp
|
|
//
|
|
//Abstract:
|
|
//
|
|
// Implementation of the CIASAttrList class.
|
|
// CIASAttrList: a list of IIASAttributeInfo interface pointers
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
#include "precompiled.h"
|
|
#include "IasAttrList.h"
|
|
#include "iasdebug.h"
|
|
#include "SafeArray.h"
|
|
#include "vendors.h"
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// Construction/Destruction
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
CIASAttrList::CIASAttrList()
|
|
{
|
|
TRACE_FUNCTION("CIASAttrList::CIASAttrList");
|
|
m_fInitialized = FALSE;
|
|
}
|
|
|
|
|
|
CIASAttrList::~CIASAttrList()
|
|
{
|
|
TRACE_FUNCTION("CIASAttrList::~CIASAttrList");
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: CIASAttrList::CreateAttribute
|
|
//
|
|
// Synopsis: Create and initialize an IIASAttributeInfo object
|
|
//
|
|
// Arguments: pIDictionary - Dictionary pointer
|
|
// AttrId - Attribute id
|
|
// tszAttrName - attribute name
|
|
//
|
|
//
|
|
// Returns: IIASAttributeInfo* - a pointer to the newly created attribute object
|
|
// NULL if anything fails
|
|
//
|
|
// History: Created Header byao 3/20/98 11:16:07 AM
|
|
//
|
|
//+---------------------------------------------------------------------------
|
|
IIASAttributeInfo* CIASAttrList::CreateAttribute( ISdoDictionaryOld* pIDictionary,
|
|
ATTRIBUTEID AttrId,
|
|
LPTSTR tszAttrName
|
|
)
|
|
{
|
|
TRACE_FUNCTION("CIASAttrList::CreateAttribute");
|
|
|
|
//
|
|
// create a safearray to get the attribuet information
|
|
//
|
|
CSafeArray<DWORD, VT_I4> InfoIds = Dim(4);
|
|
|
|
InfoIds.Lock();
|
|
InfoIds[0] = SYNTAX;
|
|
InfoIds[1] = RESTRICTIONS;
|
|
InfoIds[2] = VENDORID;
|
|
InfoIds[3] = DESCRIPTION;
|
|
InfoIds.Unlock();
|
|
|
|
CComVariant vInfoIds, vInfoValues;
|
|
|
|
SAFEARRAY sa = (SAFEARRAY)InfoIds;
|
|
V_VT(&vInfoIds) = VT_ARRAY;
|
|
V_ARRAY(&vInfoIds) = &sa;
|
|
|
|
// get the attribuet info
|
|
HRESULT hr = S_OK;
|
|
hr = pIDictionary->GetAttributeInfo(AttrId, &vInfoIds, &vInfoValues);
|
|
if ( FAILED(hr) )
|
|
{
|
|
ErrorTrace(ERROR_NAPMMC_IASATTR,"GetAttributeInfo() failed, err = %x", hr);
|
|
ShowErrorDialog(NULL
|
|
, IDS_ERROR_SDO_ERROR_GETATTRINFO
|
|
, NULL
|
|
, hr
|
|
);
|
|
return NULL;
|
|
}
|
|
|
|
_ASSERTE(V_VT(&vInfoValues) == (VT_ARRAY|VT_VARIANT) );
|
|
|
|
CSafeArray<CComVariant, VT_VARIANT> InfoValues = V_ARRAY(&vInfoValues);
|
|
|
|
InfoValues.Lock();
|
|
ATTRIBUTESYNTAX asSyntax= (ATTRIBUTESYNTAX) V_I4(&InfoValues[0]);
|
|
DWORD dwRestriction = V_I4(&InfoValues[1]);
|
|
DWORD dwVendorId = V_I4(&InfoValues[2]);
|
|
CComBSTR bstrDescription= V_BSTR(&InfoValues[3]);
|
|
InfoValues.Unlock();
|
|
|
|
//
|
|
// check whether tszDESC could be NULL -- this happens when there's no
|
|
// description for this attribute.
|
|
//
|
|
if ( ! bstrDescription )
|
|
{
|
|
bstrDescription = L" ";
|
|
}
|
|
|
|
// create the attribute ONLY if it can be in a profile or a condition
|
|
const DWORD flags = ALLOWEDINCONDITION | ALLOWEDINPROFILE |
|
|
ALLOWEDINPROXYCONDITION | ALLOWEDINPROXYPROFILE;
|
|
if (!( dwRestriction & flags ))
|
|
{
|
|
// don't create this attribute 'cause it's useless for us
|
|
return NULL;
|
|
}
|
|
|
|
CComPtr<IIASAttributeInfo> spIASAttributeInfo;
|
|
|
|
try
|
|
{
|
|
HRESULT hr;
|
|
|
|
// Decide which kind of AttributeInfo object we will need to pass attribute
|
|
// info around in -- enumerable attributes are a special case and need to
|
|
// support the IIASEnumerableAttributeInfo interface.
|
|
if ( asSyntax == IAS_SYNTAX_ENUMERATOR )
|
|
{
|
|
hr = CoCreateInstance( CLSID_IASEnumerableAttributeInfo, NULL, CLSCTX_INPROC_SERVER, IID_IIASAttributeInfo, (LPVOID *) &spIASAttributeInfo );
|
|
}
|
|
else
|
|
{
|
|
hr = CoCreateInstance( CLSID_IASAttributeInfo, NULL, CLSCTX_INPROC_SERVER, IID_IIASAttributeInfo, (LPVOID *) &spIASAttributeInfo );
|
|
}
|
|
if( FAILED(hr) ) return NULL;
|
|
|
|
|
|
// Determine the prog ID for the editor which should be used to edit
|
|
// this attribute. Make a decision based on attribute ID and/or syntax.
|
|
CComBSTR bstrEditorProgID;
|
|
if ( AttrId == RADIUS_ATTRIBUTE_VENDOR_SPECIFIC )
|
|
{
|
|
bstrEditorProgID = L"IAS.VendorSpecificAttributeEditor";
|
|
}
|
|
else if( (AttrId == MS_ATTRIBUTE_QUARANTINE_IPFILTER) ||
|
|
(AttrId == MS_ATTRIBUTE_FILTER) )
|
|
{
|
|
bstrEditorProgID = L"IAS.IPFilterAttributeEditor";
|
|
}
|
|
else
|
|
{
|
|
switch(asSyntax)
|
|
{
|
|
case IAS_SYNTAX_ENUMERATOR:
|
|
{
|
|
bstrEditorProgID = L"IAS.EnumerableAttributeEditor";
|
|
break;
|
|
}
|
|
case IAS_SYNTAX_INETADDR:
|
|
{
|
|
bstrEditorProgID = L"IAS.IPAttributeEditor";
|
|
break;
|
|
}
|
|
case IAS_SYNTAX_BOOLEAN:
|
|
{
|
|
bstrEditorProgID = L"IAS.BooleanAttributeEditor";
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
bstrEditorProgID = L"IAS.StringAttributeEditor";
|
|
}
|
|
}
|
|
}
|
|
|
|
// Store the editor Prog ID in the attribute info object.
|
|
hr = spIASAttributeInfo->put_EditorProgID( bstrEditorProgID );
|
|
if( FAILED( hr ) ) throw hr;
|
|
|
|
// Store the rest of the attribute information.
|
|
hr = spIASAttributeInfo->put_AttributeID(AttrId);
|
|
if( FAILED( hr ) ) throw hr;
|
|
|
|
hr = spIASAttributeInfo->put_AttributeSyntax(asSyntax);
|
|
if( FAILED( hr ) ) throw hr;
|
|
|
|
hr = spIASAttributeInfo->put_AttributeRestriction(dwRestriction);
|
|
if( FAILED( hr ) ) throw hr;
|
|
|
|
hr = spIASAttributeInfo->put_VendorID(dwVendorId);
|
|
if( FAILED( hr ) ) throw hr;
|
|
|
|
hr = spIASAttributeInfo->put_AttributeDescription( bstrDescription );
|
|
if( FAILED( hr ) ) throw hr;
|
|
|
|
CComBSTR bstrName = tszAttrName;
|
|
hr = spIASAttributeInfo->put_AttributeName( bstrName );
|
|
if( FAILED( hr ) ) throw hr;
|
|
|
|
// Now get the vendor name and store in the attribute.
|
|
CComBSTR bstrVendorName;
|
|
|
|
CComPtr<IIASNASVendors> spIASNASVendors;
|
|
hr = CoCreateInstance( CLSID_IASNASVendors, NULL, CLSCTX_INPROC_SERVER, IID_IIASNASVendors, (LPVOID *) &spIASNASVendors );
|
|
if( SUCCEEDED(hr) )
|
|
{
|
|
|
|
LONG lIndex;
|
|
hr = spIASNASVendors->get_VendorIDToOrdinal(dwVendorId, &lIndex);
|
|
if( S_OK == hr )
|
|
{
|
|
hr = spIASNASVendors->get_VendorName( lIndex, &bstrVendorName );
|
|
}
|
|
else
|
|
hr = ::MakeVendorNameFromVendorID(dwVendorId, &bstrVendorName );
|
|
}
|
|
|
|
// Note: If any of the above calls to the Vendor object failed,
|
|
// we will keep going, using a NULL vendor name.
|
|
hr = spIASAttributeInfo->put_VendorName( bstrVendorName );
|
|
if( FAILED( hr ) ) throw hr;
|
|
|
|
// Now store an string form describing the attribute syntax.
|
|
CComBSTR bstrSyntax;
|
|
|
|
// ISSUE: Should these all have been localized or are they some kind
|
|
// of RADIUS RFC standard? I think they should have been loaded from resources.
|
|
|
|
switch(asSyntax)
|
|
{
|
|
case IAS_SYNTAX_BOOLEAN : bstrSyntax = L"Boolean"; break;
|
|
case IAS_SYNTAX_INTEGER : bstrSyntax = L"Integer"; break;
|
|
case IAS_SYNTAX_ENUMERATOR : bstrSyntax = L"Enumerator"; break;
|
|
case IAS_SYNTAX_INETADDR : bstrSyntax = L"InetAddr"; break;
|
|
case IAS_SYNTAX_STRING : bstrSyntax = L"String"; break;
|
|
case IAS_SYNTAX_OCTETSTRING : bstrSyntax = L"OctetString"; break;
|
|
case IAS_SYNTAX_UTCTIME : bstrSyntax = L"UTCTime"; break;
|
|
case IAS_SYNTAX_PROVIDERSPECIFIC : bstrSyntax = L"ProviderSpecific"; break;
|
|
case IAS_SYNTAX_UNSIGNEDINTEGER : bstrSyntax = L"UnsignedInteger"; break;
|
|
default : bstrSyntax = L"Unknown Type"; break;
|
|
}
|
|
|
|
hr = spIASAttributeInfo->put_SyntaxString( bstrSyntax );
|
|
if( FAILED(hr) ) throw hr;
|
|
}
|
|
catch (...)
|
|
{
|
|
_ASSERTE( FALSE );
|
|
ErrorTrace(ERROR_NAPMMC_IASATTRLIST, "Can't create the attribute ,err = %x", GetLastError());
|
|
return NULL;
|
|
}
|
|
|
|
// clean up -- we don't need to clean up vInfoIds. It's deleted by ~CSafeArray()
|
|
// VariantClear(&vInfoValues);
|
|
|
|
//
|
|
// 3) get the value list for this attribute, if it's enumerator
|
|
//
|
|
if ( asSyntax == IAS_SYNTAX_ENUMERATOR )
|
|
{
|
|
// get the enumerable list for this attribute
|
|
CComVariant varValueIds, varValueNames;
|
|
|
|
hr = pIDictionary->EnumAttributeValues(AttrId,
|
|
&varValueIds,
|
|
&varValueNames);
|
|
if ( SUCCEEDED(hr) )
|
|
{
|
|
_ASSERTE(V_VT(&varValueNames) == (VT_ARRAY|VT_VARIANT) );
|
|
_ASSERTE(V_VT(&varValueIds) & (VT_ARRAY|VT_I4) );
|
|
|
|
|
|
// Up above, if the attribute was enumerable, we created
|
|
// an attribute info object which implements the IIASEnumerableAttributeInfo
|
|
// interface. We query for this interface now
|
|
// and load all the enumerates from pAttr into that
|
|
// interface of the shema attribute.
|
|
CComQIPtr< IIASEnumerableAttributeInfo, &IID_IIASEnumerableAttributeInfo > spIASEnumerableAttributeInfo( spIASAttributeInfo );
|
|
if( ! spIASEnumerableAttributeInfo ) return NULL;
|
|
|
|
|
|
// Make sure that the list of enumerates in consistent.
|
|
// There should be a 1-1 correspondence between ID's and description strings.
|
|
|
|
//ISSUE: todo _ASSERTE( lSize == pAttr->m_arrValueIdList.GetSize() );
|
|
|
|
// get the safearray data
|
|
CSafeArray<CComVariant, VT_VARIANT> ValueIds = V_ARRAY(&varValueIds);
|
|
CSafeArray<CComVariant, VT_VARIANT> ValueNames = V_ARRAY(&varValueNames);
|
|
|
|
ValueIds.Lock();
|
|
ValueNames.Lock();
|
|
|
|
int iSize = ValueIds.Elements();
|
|
for (int iValueIndex=0; iValueIndex < iSize; iValueIndex++)
|
|
{
|
|
// ISSUE: Make sure this deep copies the name.
|
|
CComBSTR bstrValueName = V_BSTR(&ValueNames[iValueIndex]);
|
|
|
|
hr = spIASEnumerableAttributeInfo->AddEnumerateDescription( bstrValueName );
|
|
if( FAILED( hr ) ) return NULL;
|
|
|
|
VARIANT * pVar = &ValueIds[iValueIndex];
|
|
|
|
long lID = V_I4( pVar );
|
|
|
|
hr = spIASEnumerableAttributeInfo->AddEnumerateID( lID );
|
|
if( FAILED( hr ) ) return NULL;
|
|
|
|
}
|
|
|
|
ValueIds.Unlock();
|
|
ValueNames.Unlock();
|
|
}
|
|
else
|
|
{
|
|
// can't get the list.
|
|
//todo: need any action here?
|
|
hr = S_OK;
|
|
}
|
|
}
|
|
|
|
// Note: We have a bit of a RefCounting issue here.
|
|
// As soon as we leave this function, desstructor for CComPtr
|
|
// will be called, Release'ing the IIASAttributeInfo interface.
|
|
// This will happen before the CComPtr on the other side has
|
|
// had a chance to AddRef it.
|
|
// As a temporary hack, we AddRef here and release on the other side.
|
|
spIASAttributeInfo.p->AddRef();
|
|
return spIASAttributeInfo.p;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: Init
|
|
//
|
|
// Class: CIASAttrList
|
|
//
|
|
// Synopsis: Populate the condition attribute list. Do nothing
|
|
// if the list is already populated
|
|
//
|
|
// Arguments: [in]ISdo *pIDictionarySdo: dictionary sdo
|
|
//
|
|
// Returns: HRESULT -
|
|
//
|
|
// History: Created Header byao 2/16/98 4:57:07 PM
|
|
//
|
|
//+---------------------------------------------------------------------------
|
|
HRESULT CIASAttrList::Init(ISdoDictionaryOld *pIDictionarySdo)
|
|
{
|
|
TRACE_FUNCTION("CIASAttrList::Init");
|
|
|
|
_ASSERTE( pIDictionarySdo != NULL );
|
|
|
|
if (m_fInitialized)
|
|
{
|
|
//
|
|
// the list has already been populated -- do nothing
|
|
//
|
|
return S_OK;
|
|
}
|
|
|
|
// The push_back call below can throw an exception.
|
|
try
|
|
{
|
|
|
|
//
|
|
// Get all the attributes that can be used in a condition
|
|
//
|
|
int iIndex;
|
|
HRESULT hr = S_OK;
|
|
CComVariant vNames;
|
|
CComVariant vIds;
|
|
|
|
hr = pIDictionarySdo -> EnumAttributes(&vIds, &vNames);
|
|
if ( FAILED(hr) )
|
|
{
|
|
ErrorTrace(ERROR_NAPMMC_IASATTRLIST, "EnumAttributes() failed, err = %x", hr);
|
|
ShowErrorDialog(NULL
|
|
, IDS_ERROR_SDO_ERROR_ENUMATTR
|
|
, NULL
|
|
, hr
|
|
);
|
|
return hr;
|
|
}
|
|
|
|
_ASSERTE(V_VT(&vIds) == (VT_ARRAY|VT_I4) );
|
|
_ASSERTE(V_VT(&vNames) == (VT_ARRAY|VT_VARIANT) );
|
|
|
|
CSafeArray<DWORD, VT_I4> AttrIds = V_ARRAY(&vIds);
|
|
CSafeArray<CComVariant, VT_VARIANT> AttrNames = V_ARRAY(&vNames);
|
|
|
|
AttrIds.Lock();
|
|
AttrNames.Lock();
|
|
|
|
for (iIndex = 0; iIndex < AttrIds.Elements(); iIndex++)
|
|
{
|
|
// create an attribute object
|
|
DebugTrace(DEBUG_NAPMMC_IASATTRLIST, "Creating an attribute, name = %ws", V_BSTR(&AttrNames[iIndex]) );
|
|
|
|
_ASSERTE( V_BSTR(&AttrNames[iIndex]) );
|
|
CComPtr<IIASAttributeInfo> spAttributeInfo = CreateAttribute(pIDictionarySdo,
|
|
(ATTRIBUTEID)AttrIds[iIndex],
|
|
V_BSTR(&AttrNames[iIndex])
|
|
);
|
|
|
|
|
|
if ( ! spAttributeInfo )
|
|
{
|
|
continue; // create the next attribute
|
|
}
|
|
|
|
// See note in CreateAttribute for why we Release here.
|
|
spAttributeInfo.p->Release();
|
|
|
|
m_AttrList.push_back(spAttributeInfo);
|
|
} // for
|
|
|
|
AttrIds.Unlock();
|
|
AttrNames.Unlock();
|
|
|
|
m_fInitialized = TRUE;
|
|
}
|
|
catch(...)
|
|
{
|
|
return E_FAIL;
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: GetSize
|
|
//
|
|
// Class: CIASAttrList
|
|
//
|
|
// Synopsis: get the number of elements in the condition attribute list
|
|
//
|
|
// Arguments: None
|
|
//
|
|
// Returns: DWORD - list length
|
|
//
|
|
// History: Created Header byao 2/16/98 8:11:17 PM
|
|
//
|
|
//+---------------------------------------------------------------------------
|
|
DWORD CIASAttrList::size() const
|
|
{
|
|
if (!m_fInitialized)
|
|
{
|
|
::MessageBox(NULL,L"populate the list first!", L"", MB_OK);
|
|
return E_NOTIMPL;
|
|
}
|
|
else
|
|
{
|
|
return m_AttrList.size();
|
|
}
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: operator[]
|
|
//
|
|
// Class: CIASAttrList
|
|
//
|
|
// Synopsis: get the condition attribute pointer at index [nIndex]
|
|
//
|
|
// Arguments: int nIndex - index
|
|
//
|
|
// Returns: IIASAttributeInfo* : pointer to a condition attribute object
|
|
//
|
|
// History: Created Header byao 2/16/98 8:16:37 PM
|
|
//
|
|
//+---------------------------------------------------------------------------
|
|
IIASAttributeInfo* CIASAttrList:: operator[] (int nIndex) const
|
|
{
|
|
if (!m_fInitialized)
|
|
{
|
|
::MessageBox(NULL,L"populate the list first!", L"", MB_OK);
|
|
return NULL;
|
|
}
|
|
else
|
|
{
|
|
_ASSERTE(nIndex >= 0 && nIndex < m_AttrList.size());
|
|
return m_AttrList[nIndex].p;
|
|
}
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: GetAt()
|
|
//
|
|
// Class: CIASAttrList
|
|
//
|
|
// Synopsis: get the condition attribute pointer at nIndex
|
|
//
|
|
// Arguments: int nIndex - index
|
|
//
|
|
// Returns: IIASAttributeInfo* : pointer to a condition attribute object
|
|
//
|
|
// History: Created Header byao 2/16/98 8:16:37 PM
|
|
//
|
|
//+---------------------------------------------------------------------------
|
|
IIASAttributeInfo* CIASAttrList:: GetAt(int nIndex) const
|
|
{
|
|
TRACE_FUNCTION("CIASAttrList::GetAt");
|
|
|
|
if (!m_fInitialized)
|
|
{
|
|
ErrorTrace(ERROR_NAPMMC_IASATTRLIST, "The list is NOT initialized!");
|
|
return NULL;
|
|
}
|
|
else
|
|
{
|
|
_ASSERTE(nIndex >= 0 && nIndex < m_AttrList.size());
|
|
return m_AttrList[nIndex].p;
|
|
}
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: CIASAttrList::Find
|
|
//
|
|
// Synopsis: Find an attribute based on attribute ID
|
|
//
|
|
// Arguments: ATTRIBUTEID AttrId - attribute id
|
|
//
|
|
// Returns: int - index in the list
|
|
//
|
|
// History: Created Header 2/22/98 1:52:36 AM
|
|
//
|
|
//+---------------------------------------------------------------------------
|
|
int CIASAttrList::Find(ATTRIBUTEID AttrId)
|
|
{
|
|
int iIndex;
|
|
|
|
// The operator [] below can throw exceptions.
|
|
try
|
|
{
|
|
for (iIndex=0; iIndex<m_AttrList.size(); iIndex++)
|
|
{
|
|
ATTRIBUTEID id;
|
|
m_AttrList[iIndex]->get_AttributeID( &id );
|
|
if( id == AttrId )
|
|
{
|
|
// found
|
|
return iIndex;
|
|
}
|
|
}
|
|
}
|
|
catch(...)
|
|
{
|
|
// Just catch the exception -- we'll return -1 below.
|
|
}
|
|
|
|
// not found
|
|
return -1;
|
|
}
|