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.
 
 
 
 
 
 

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;
}