windows-nt/Source/XPSP1/NT/net/mmc/acssnap/acsdata.h
2020-09-26 16:20:57 +08:00

1420 lines
40 KiB
C++

/**********************************************************************/
/** Microsoft Windows/NT **/
/** Copyright(c) Microsoft Corporation, 1997 - 1999 **/
/**********************************************************************/
/*
ACSData.h
Defines the DataObject classes used in ACS
FILE HISTORY:
11/11/97 Wei Jiang Created
*/
#ifndef _ACSDATA_H_
#define _ACSDATA_H_
#include <list>
#include <functional>
#include <algorithm>
#include "..\common\dataobj.h"
class CACSHandle;
// ACS data state
// CDSObject has virtual function to test state
// CACSHandle has virtual function to show state
// currently, only for acspolicy to show confilict state
#define ACSDATA_STATE_CONFLICT 0x00000001
#define ACSDATA_STATE_DISABLED 0x00000002
#define ACSDATA_STATE_NOOBJECT 0x00000004 // no policy defined for the subnet
#define ERROR_NO_SUCH_OBJECT 0x80072030
#define ATTR_FLAGS_ALL 0xffffffff
#define ATTR_FLAGS_NONE 0x0
#define TOMB(n) ((n) / 1024 / 1024)
#define FROMMB(n) ((n) * 1024 * 1024)
#define TOKBS(n) ((n) / 1024)
#define FROMKBS(n) ((n) * 1024)
#define MIN2SEC(n) ((n) * 60)
#define SEC2MIN(n) ((n) / 60)
#define IS_LARGE_UNLIMIT(large) ((large).LowPart == 0xffffffff && (large).HighPart == 0xffffffff)
#define SET_LARGE_UNLIMIT(large) ((large.LowPart = 0xffffffff),(large.HighPart = 0xffffffff))
#define UNLIMIT 0xffffffff
#define SET_LARGE(l, h, lo) ((l).LowPart = (lo), (l).HighPart = (h))
#define ACSPOLICY_DEFAULT _T("AcsPolicy0")
#define ACSPOLICY_UNKNOWN _T("AcsPolicy1")
// to check if the mentioned attribute will have data after the next save
#define ATTR_WILL_EXIST_AFTER_SAVE(a, toBeSaved) \
(((toBeSaved & a) != 0 && GetFlags(ATTR_FLAG_SAVE, a) != 0 ) || \
((toBeSaved & a) == 0 && GetFlags(ATTR_FLAG_LOAD, a) != 0 ) )
/*
When you create the global conatiner and the Authenticated and
UnAuthenticated user objects you need to set the following default values:
Authenticated user :
Data rate: 500 Kbits/sec
Peak Data rate: 500 kbits/sec
Number of flows : 2
UnAuthenticated user :
Data rate: 64 Kbits/sec
Peak data rate: 64 kbits/sec
Number of flows : 1
*/
#define ACS_GLOBAL_DEFAULT_DATARATE FROMKBS(500)
#define ACS_GLOBAL_DEFAULT_PEAKRATE FROMKBS(500)
#define ACS_GLOBAL_DEFAULT_FLOWS 2
#define ACS_GLOBAL_UNKNOWN_DATARATE FROMKBS(64)
#define ACS_GLOBAL_UNKNOWN_PEAKRATE FROMKBS(64)
#define ACS_GLOBAL_UNKNOWN_FLOWS 1
///////////////////////////////////////////////////////////////////////////////
// CIDSDataObject
// Support Addtional format -- CFSTR_DSOBJECTNAMES
//
class CDSIDataObject : public CDataObject
{
public:
CDSIDataObject()
{
m_bstrADsPath = NULL;
m_bstrClass = NULL;
};
virtual ~CDSIDataObject()
{
SysFreeString(m_bstrADsPath);
SysFreeString(m_bstrClass);
}
public:
// Implemented functions of IDataObject
STDMETHOD(GetData)(FORMATETC * pformatetcIn, STGMEDIUM * pmedium);
void SetStrings(BSTR path, BSTR cls){m_bstrADsPath = path; m_bstrClass = cls;};
protected:
BSTR m_bstrADsPath;
BSTR m_bstrClass;
// Property Page Clipboard formats
static UINT m_cfDsObjectNames;
};
///////////////////////////////////////////////////////////////////////////////
// CDSAttributes
//
struct CDSAttributeInfo
{
int id;
WCHAR* name;
ADSTYPE type;
bool ifMultiValued;
DWORD flag;
};
struct CDSAttribute
{
CDSAttributeInfo* pInfo;
void* pBuffer;
};
// maximum number of attribute supported
#define MAX_ATTRIBUTES 32
enum ATTR_FLAG {
ATTR_FLAG_LOAD = 0,
ATTR_FLAG_SAVE,
ATTR_FLAG_TOTAL
};
/////////////////////////////////////////////////////////////////////////////
// CDSObject
class ATL_NO_VTABLE CDSObject :
public CComObjectRootEx<CComSingleThreadModel>,
// public CComCoClass<CDSObject, &CLSID_DSObject>,
public IUnknown
{
BEGIN_COM_MAP(CDSObject)
COM_INTERFACE_ENTRY(IUnknown)
END_COM_MAP()
CDSObject(bool bNoRefCountOnContainer = FALSE); // when container keeps ref count of
// the this child, set bNoRefCountOnContainer to true
virtual ~CDSObject();
public:
// its own functions
// Set information about the DS object, without opening it
STDMETHOD(SetInfo)( CDSObject* pContainer, // container
LPCWSTR clsName, // class name
LPCWSTR objName // object name
);
// load from DS -- derived need to override, when need to load data
STDMETHOD(Open)( CDSObject* pContainer, // container
LPCWSTR clsName, // class name
LPCWSTR objName, // object name
bool bCreateIfNonExist, // if create, [in, out]
bool bPersistWhenCreate = true
);
virtual void SetHandle(CACSHandle* pHandle){ ASSERT(pHandle); m_pHandle = pHandle;};
// load from DS -- derived need to override, when need to load data
STDMETHOD(Reopen)();
// load from DS -- derived need to override, when need to load data
STDMETHOD(Attach)( CDSObject* pContainer, // container
IADs* pIObject
);
// release the pointers, and free the buffer
STDMETHOD(Close)();
// save to DS -- derived must override
STDMETHOD(Save)(DWORD dwAttrFlags);
// delete the object from DS -- usually not override
STDMETHOD(Delete)();
// rename the DS object -- usually not override
STDMETHOD(Rename)(LPCWSTR szName);
// called after the object is created, before it actually become persist
// derived class should set attribute values of the object
// m_pIObject, m_pIContainer are available to use
// initialize the attributes in DS should be done in this function
STDMETHOD(OnCreate)(DWORD* pdwAttrFlags) { *pdwAttrFlags = 0xffffffff; return S_OK;};
// called after the object is open,
// m_pIObject, m_pIContainer are available to use
// read attributes from DS should be done in this function
STDMETHOD(OnOpen)() SAYOK;
// called before SetInfo is called to set the object
// m_pIObject, m_pIContainer are available to use
// write attributes to DS should be done in this function
STDMETHOD(OnSave)(DWORD dwAttrFlags) SAYOK;
// called after the object is open,
// m_pIObject, m_pIContainer are available to use
// read attributes from DS should be done in this function
STDMETHOD(LoadAttributes)();
// called before SetInfo is called to set the object
// m_pIObject, m_pIContainer are available to use
// write attributes to DS should be done in this function
STDMETHOD(SaveAttributes)(DWORD dwAttrFlags);
//=========================================
// functions about container
// add a child object to this container
STDMETHOD(AddChild)(CDSObject* pObject) SAYOK;
// remove a child object from this container
STDMETHOD(RemoveChild)(CDSObject* pObject) SAYOK;
// remove all children object from this container
STDMETHOD(RemoveAllChildren)(CDSObject* pObject) SAYOK;
// ===========================================
// get the data memebers
STDMETHOD(GetIADs)(IADs** ppIADs);
// ===========================================
// get the data memebers
STDMETHOD(GetString)(CString& str, int nCol);
// when object is not in the DS
HRESULT SetNoObjectState()
{
DWORD state = GetState();
if (Reopen() == ERROR_NO_SUCH_OBJECT)
{
SetState(state | ACSDATA_STATE_NOOBJECT);
return S_FALSE;
}
else
{
SetState(state & (~ACSDATA_STATE_NOOBJECT));
return S_OK;
}
};
STDMETHOD_(LPCWSTR, GetName)() { return m_bstrName + 3; /* L"CN="*/};
STDMETHOD_(LPCWSTR, GetADsPath)() { return m_bstrADsPath;};
STDMETHOD_(LPCWSTR, GetClass)() { return m_bstrClass;};
STDMETHOD_(CDSObject*, GetContainer)()
{
if((CDSObject*)m_spContainer)
m_spContainer->AddRef();
return (CDSObject*)m_spContainer;
};
STDMETHOD_(CStrArray*, GetChildrenNameList)() { return NULL;};
virtual CDSAttribute* GetAttributes() { return NULL;};
// load attribute changes the flags, and save attribute uses the flag
DWORD GetFlags(ATTR_FLAG load_or_save, DWORD flags)
{
ASSERT(load_or_save < ATTR_FLAG_TOTAL);
return (m_dwAttributeFlags[load_or_save] & flags);
};
void ClearFlags(ATTR_FLAG load_or_save)
{
ASSERT(load_or_save < ATTR_FLAG_TOTAL);
m_dwAttributeFlags[load_or_save] = 0;
};
void SetFlags(ATTR_FLAG load_or_save, DWORD flags, bool bSet)
{
ASSERT(load_or_save < ATTR_FLAG_TOTAL);
if(bSet)
m_dwAttributeFlags[load_or_save] |= flags;
else // clear the flags
m_dwAttributeFlags[load_or_save] &= (~flags);
};
virtual HRESULT SetState(DWORD state);
virtual DWORD GetState() { return m_dwState;};
HRESULT MakeSureExist(BOOL *pNewCreated)
{
HRESULT hr = Reopen();
if(hr == ERROR_NO_SUCH_OBJECT) // not exist
{
ASSERT(m_spContainer.p && m_bstrClass && m_bstrName);
hr = Open(m_spContainer, m_bstrClass, m_bstrName, true /* create if non exist*/, true /* not persist when create */);
if(pNewCreated)
*pNewCreated = TRUE;
}
else if(pNewCreated)
*pNewCreated = FALSE;
return hr;
};
// return resource error ID, 0 means OK
virtual UINT PreSaveVerifyData(DWORD toBeSavedAttributes) { return 0;};
bool IfOpened() { return (m_spIADs.p != NULL);};
bool IfNewCreated() { return m_bNewCreated;};
//================================================
// protected data section
protected:
CComPtr<IADs> m_spIADs;
CComPtr<CDSObject> m_spContainer;
BSTR m_bstrADsPath;
BSTR m_bstrClass;
BSTR m_bstrName;
bool m_bNewCreated;
bool m_bNoRefCountOnContainer;
bool m_bOpened;
CACSHandle* m_pHandle; // not ref counted
DWORD m_dwState; // the state of the object, current being used by policy to show conflict
// used set if an paricular attribute are loaded, or need to be saved
DWORD m_dwAttributeFlags[ATTR_FLAG_TOTAL];
};
//=============================================================================
// container object for subnetworks container and policy container
template <class T>
class CACSContainerObject : public CDSObject
{
public:
CACSContainerObject(bool bNoRefCountOnContainer = FALSE) : CDSObject(bNoRefCountOnContainer)
{
m_bListed = false;
}
virtual ~CACSContainerObject()
{
m_listChildrenName.DeleteAll();
}
public:
//=========================================
// functions about container
// add a child object to this container
STDMETHOD(AddChild)(CDSObject* pObject)
{
CString* pStr = new CString();
*pStr = pObject->GetName();
m_listChildrenName.Add(pStr);
// childrenlist
m_listChildren.push_back(pObject);
return S_OK;
}
// remove a child object from this container
STDMETHOD(RemoveChild)(CDSObject* pObject)
{
// childrenlist
std::list<CDSObject*>::iterator j;
j = std::find(m_listChildren.begin(), m_listChildren.end(), pObject);
if(j!= m_listChildren.end())
m_listChildren.erase(j);
// name list
CString Str;
Str = pObject->GetName();
int i = m_listChildrenName.Find(Str);
if(i >= 0)
{
CString* pStr = m_listChildrenName[(INT_PTR)i];
m_listChildrenName.RemoveAt(i);
delete pStr;
return S_OK;
}
else
return S_FALSE;
};
// remove all children object from this container
STDMETHOD(RemoveAllChildren)()
{
// childrenlist
m_listChildren.erase(m_listChildren.begin(), m_listChildren.end());
m_listChildrenName.DeleteAll();
return S_OK;
};
// delete the object from DS -- usually not override
STDMETHOD(Delete)()
{
HRESULT hr = CDSObject::Delete();
if (hr == S_OK)
RemoveAllChildren();
return hr;
};
// create DSObject(Type T) for children under the container,
// create the children name list at the same time
HRESULT ListChildren(std::list<T*>& children, BSTR clsName);
STDMETHOD_(CStrArray*, GetChildrenNameList)()
{
if(!m_bListed)
{
std::list<T*> children;
if(S_OK != ListChildren(children, NULL))
return NULL;
}
return &m_listChildrenName;
};
//================================================
// protected data section
protected:
//== list of children's name
CStrArray m_listChildrenName;
std::list<CDSObject*> m_listChildren; // no ref count on children
bool m_bListed;
};
///////////////////////////////////////////////////////////////////////////////
//
// CACSPolicyElement : policy in DS is still a folder which is capable of
// holding multiple policy data
// while, for this version there is one DS object with predefined
// name defined in policy folder
//
enum ACS_POLICY_ATTRIBUTE_ID {
ACS_PAI_INVALID = 0 ,
ACS_PAI_TIMEOFDAY ,
ACS_PAI_DIRECTION ,
ACS_PAI_PF_TOKENRATE ,
ACS_PAI_PF_PEAKBANDWIDTH,
ACS_PAI_PF_DURATION ,
ACS_PAI_SERVICETYPE ,
ACS_PAI_PRIORITY ,
ACS_PAI_PERMISSIONBITS ,
ACS_PAI_TT_FLOWS ,
ACS_PAI_TT_PEAKBANDWIDTH,
ACS_PAI_TT_TOKENRATE ,
ACS_PAI_IDENTITYNAME,
__ACS_PAI_COUNT
};
// flag for each attribute
#define ACS_PAF_TIMEOFDAY 0x00000001
#define ACS_PAF_DIRECTION 0x00000002
#define ACS_PAF_PF_TOKENRATE 0x00000004
#define ACS_PAF_PF_PEAKBANDWIDTH 0x00000008
#define ACS_PAF_PF_DURATION 0x00000010
#define ACS_PAF_SERVICETYPE 0x00000020
#define ACS_PAF_PRIORITY 0x00000040
#define ACS_PAF_PERMISSIONBITS 0x00000080
#define ACS_PAF_TT_FLOWS 0x00000100
#define ACS_PAF_TT_TOKENRATE 0x00000200
#define ACS_PAF_TT_PEAKBANDWIDTH 0x00000400
#define ACS_PAF_IDENTITYNAME 0x00000800
class CPgTraffic;
struct CACSPolicyElementData{
// data memebers of policy
CStrArray m_strArrayTimeOfDay; // not support in this version
ADS_INTEGER m_dwDirection;
ADS_LARGE_INTEGER m_ddPFTokenRate;
ADS_LARGE_INTEGER m_ddPFPeakBandWidth;
ADS_INTEGER m_dwPFDuration;
ADS_INTEGER m_dwServiceType;
ADS_INTEGER m_dwPriority;
ADS_LARGE_INTEGER m_ddPermissionBits;
ADS_INTEGER m_dwTTFlows;
ADS_LARGE_INTEGER m_ddTTPeakBandWidth;
ADS_LARGE_INTEGER m_ddTTTokenRate;
CStrArray m_strArrayIdentityName;
CACSPolicyElementData()
{
m_dwDirection = 0;
SET_LARGE(m_ddPFTokenRate,0,0);
SET_LARGE(m_ddPFPeakBandWidth, 0, 0);
m_dwPFDuration = 0;
m_dwServiceType = 0;
m_dwPriority = 0;
SET_LARGE(m_ddPermissionBits,0,0);
m_dwTTFlows = 0;
SET_LARGE(m_ddTTPeakBandWidth,0,0);
SET_LARGE(m_ddTTTokenRate,0,0);
};
~CACSPolicyElementData(){
m_strArrayIdentityName.DeleteAll();
};
};
enum AcsPolicyType
{
ACSPOLICYTYPE_DEFAULT,
ACSPOLICYTYPE_UNKNOWN,
ACSPOLICYTYPE_USER,
ACSPOLICYTYPE_OU
};
#define ACSPOLICYTYPE_DELIMITER _T(':')
// enterprise level default
#define DEFAULT_AU_DATARATE FROMKBS(64) // default data rate for Any Unauthenticated User
#define DEFAULT_AA_DATARATE FROMKBS(500) // default data rate for Any Authenticated User
enum UserPolicyType
{
UNDEFINED = 0,
GLOBAL_ANY_AUTHENTICATED,
GLOBAL_ANY_UNAUTHENTICATED,
};
class CACSPolicyContainer;
//
// IdentityName attribute of policy is as format
// 2:USerDN or 3:OUDN or 0 or 1 0-- for default, 1-- for unknown
//
class CACSPolicyElement : public CDSObject, public CACSPolicyElementData
{
public:
~CACSPolicyElement()
{
};
CACSPolicyElement() : CDSObject(true)
{
void* pVoid;
CDSAttributeInfo* pInfo = m_aPolicyAttributeInfo;
m_bUseName_NewPolicy = FALSE;
int count = 0;
while(pInfo && pInfo->id)
{
m_aAttributes[count].pInfo = pInfo;
switch(pInfo->id)
{
case ACS_PAI_TIMEOFDAY: pVoid = (void*)&m_strArrayTimeOfDay; break;// n
case ACS_PAI_DIRECTION: pVoid = (void*)&m_dwDirection; break;
case ACS_PAI_PF_TOKENRATE: pVoid = (void*)&m_ddPFTokenRate; break;
case ACS_PAI_PF_PEAKBANDWIDTH: pVoid = (void*)&m_ddPFPeakBandWidth; break;
case ACS_PAI_PF_DURATION: pVoid = (void*)&m_dwPFDuration; break;
case ACS_PAI_SERVICETYPE: pVoid = (void*)&m_dwServiceType; break;
case ACS_PAI_PRIORITY: pVoid = (void*)&m_dwPriority; break;
case ACS_PAI_PERMISSIONBITS: pVoid = (void*)&m_ddPermissionBits; break;
case ACS_PAI_TT_FLOWS: pVoid = (void*)&m_dwTTFlows; break;
case ACS_PAI_TT_PEAKBANDWIDTH: pVoid = (void*)&m_ddTTPeakBandWidth; break;
case ACS_PAI_TT_TOKENRATE: pVoid = (void*)&m_ddTTTokenRate; break;
case ACS_PAI_IDENTITYNAME: pVoid = (void*)&m_strArrayIdentityName; break;
default: ASSERT(0); break; // this should NOT happen
}
m_aAttributes[count++].pBuffer = pVoid;
pInfo++;
}
m_aAttributes[count].pInfo = 0;
m_aAttributes[count].pBuffer = 0;
};
DWORD SetGlobalDefault()
// returning the flags which are the attributes have been set
{
// Direction and Service Type
m_dwDirection = ACS_DIRECTION_BOTH;
m_dwServiceType = ACS_SERVICETYPE_ALL;
// make it Default
CString* pStr = new CString(_T("0"));
m_strArrayIdentityName.DeleteAll();
m_strArrayIdentityName.Add(pStr);
// Per flow rate
// Total
m_dwTTFlows = ACS_GLOBAL_DEFAULT_FLOWS;
m_ddTTTokenRate.LowPart = ACS_GLOBAL_DEFAULT_DATARATE;
m_ddTTTokenRate.HighPart = 0;
m_ddTTPeakBandWidth.LowPart = ACS_GLOBAL_DEFAULT_PEAKRATE;
m_ddTTPeakBandWidth.HighPart = 0;
return (ACS_PAF_DIRECTION | ACS_PAF_SERVICETYPE | ACS_PAF_IDENTITYNAME // dirction, service type, identity
// per flow
| ACS_PAF_TT_FLOWS | ACS_PAF_TT_TOKENRATE | ACS_PAF_TT_PEAKBANDWIDTH); // total
};
// return resource error ID, 0 means OK
virtual UINT PreSaveVerifyData(DWORD toBeSavedAttributes, UserPolicyType type)
{
// special checking for Global Any Authenticated, and Any Unauthenticated
if(type == GLOBAL_ANY_AUTHENTICATED || type == GLOBAL_ANY_UNAUTHENTICATED)
{
UINT dataRateLimit;
if(type == GLOBAL_ANY_AUTHENTICATED)
dataRateLimit = DEFAULT_AA_DATARATE;
else
dataRateLimit = DEFAULT_AU_DATARATE;
// total data rate and data rate -- one of them set to default
if(ATTR_WILL_EXIST_AFTER_SAVE(ACS_PAF_PF_TOKENRATE, toBeSavedAttributes)
&& ATTR_WILL_EXIST_AFTER_SAVE( ACS_PAF_TT_TOKENRATE, toBeSavedAttributes) == 0
&& (!IS_LARGE_UNLIMIT(m_ddPFTokenRate))
&& m_ddPFTokenRate.LowPart > dataRateLimit)
return IDS_ERR_TOTALRATE_LESS_RATE;
if(ATTR_WILL_EXIST_AFTER_SAVE(ACS_PAF_PF_TOKENRATE, toBeSavedAttributes) == 0
&& ATTR_WILL_EXIST_AFTER_SAVE( ACS_PAF_TT_TOKENRATE, toBeSavedAttributes)
&& (!IS_LARGE_UNLIMIT(m_ddTTTokenRate))
&& dataRateLimit > m_ddTTTokenRate.LowPart)
return IDS_ERR_TOTALRATE_LESS_RATE;
}
// data rate .. peak data rate
if(ATTR_WILL_EXIST_AFTER_SAVE(ACS_PAF_PF_TOKENRATE, toBeSavedAttributes)
&& ATTR_WILL_EXIST_AFTER_SAVE(ACS_PAF_PF_PEAKBANDWIDTH, toBeSavedAttributes)
&& (!IS_LARGE_UNLIMIT(m_ddPFTokenRate)) && (!IS_LARGE_UNLIMIT(m_ddPFPeakBandWidth))
&& m_ddPFTokenRate.LowPart > m_ddPFPeakBandWidth.LowPart)
return IDS_ERR_PEAKRATE_LESS_RATE;
// total data rate and data rate
if(ATTR_WILL_EXIST_AFTER_SAVE(ACS_PAF_PF_TOKENRATE, toBeSavedAttributes)
&& ATTR_WILL_EXIST_AFTER_SAVE( ACS_PAF_TT_TOKENRATE, toBeSavedAttributes)
&& (!IS_LARGE_UNLIMIT(m_ddPFTokenRate)) && (!IS_LARGE_UNLIMIT(m_ddTTTokenRate))
&& m_ddPFTokenRate.LowPart > m_ddTTTokenRate.LowPart)
return IDS_ERR_TOTALRATE_LESS_RATE;
// total data rate and total peak ...
if(ATTR_WILL_EXIST_AFTER_SAVE(ACS_PAF_TT_PEAKBANDWIDTH, toBeSavedAttributes)
&& ATTR_WILL_EXIST_AFTER_SAVE( ACS_PAF_TT_TOKENRATE, toBeSavedAttributes)
&& (!IS_LARGE_UNLIMIT(m_ddTTTokenRate)) && (!IS_LARGE_UNLIMIT(m_ddTTPeakBandWidth))
&& m_ddTTTokenRate.LowPart > m_ddTTPeakBandWidth.LowPart)
return IDS_ERR_TOTALPEAK_LESS_TOTALRATE;
// peak rate and total peak
if(ATTR_WILL_EXIST_AFTER_SAVE( ACS_PAF_TT_PEAKBANDWIDTH, toBeSavedAttributes)
&& ATTR_WILL_EXIST_AFTER_SAVE(ACS_PAF_PF_PEAKBANDWIDTH, toBeSavedAttributes)
&& (!IS_LARGE_UNLIMIT(m_ddPFPeakBandWidth)) && (!IS_LARGE_UNLIMIT(m_ddTTPeakBandWidth))
&& m_ddPFPeakBandWidth.LowPart > m_ddTTPeakBandWidth.LowPart)
return IDS_ERR_TOTALPEAK_LESS_PEAK;
return 0;
};
DWORD SetGlobalUnknown()
// returning the flags which are the attributes have been set
{
// Direction and ServiceType
m_dwDirection = ACS_DIRECTION_BOTH;
m_dwServiceType = ACS_SERVICETYPE_ALL;
CString* pStr = new CString(_T("1"));
m_strArrayIdentityName.DeleteAll();
m_strArrayIdentityName.Add(pStr);
// Per flow
// Total
m_dwTTFlows = ACS_GLOBAL_UNKNOWN_FLOWS;
m_ddTTTokenRate.LowPart = ACS_GLOBAL_UNKNOWN_DATARATE;
m_ddTTTokenRate.HighPart = 0;
m_ddTTPeakBandWidth.LowPart = ACS_GLOBAL_UNKNOWN_PEAKRATE;
m_ddTTPeakBandWidth.HighPart = 0;
return (ACS_PAF_DIRECTION | ACS_PAF_SERVICETYPE | ACS_PAF_IDENTITYNAME // dirction, service type, identity
// per flow
| ACS_PAF_TT_FLOWS | ACS_PAF_TT_TOKENRATE | ACS_PAF_TT_PEAKBANDWIDTH); // total
};
DWORD SetDefault()
// returning the flags which are the attributes have been set
{
// Direction and ServiceType
m_dwDirection = ACS_DIRECTION_BOTH;
m_dwServiceType = ACS_SERVICETYPE_ALL;
CString* pStr = new CString(_T("0"));
m_strArrayIdentityName.Add(pStr);
return (ACS_PAF_DIRECTION | ACS_PAF_SERVICETYPE | ACS_PAF_IDENTITYNAME);
};
DWORD SetUnknown()
// returning the flags which are the attributes have been set
{
// Direction and ServiceType
m_dwDirection = ACS_DIRECTION_BOTH;
m_dwServiceType = ACS_SERVICETYPE_ALL;
CString* pStr = new CString(_T("1"));
m_strArrayIdentityName.Add(pStr);
return (ACS_PAF_DIRECTION | ACS_PAF_SERVICETYPE | ACS_PAF_IDENTITYNAME);
};
virtual CDSAttribute* GetAttributes() { return &(m_aAttributes[0]);};
// identity type
int GetIdentityType(int* pStrOffset) const // return -1, of the type is not recognized, or IdentityName doesn't exist
{
if(m_strArrayIdentityName.GetSize() == 0) return -1;
ASSERT(m_strArrayIdentityName.GetSize() == 1); // more than one is not expected in this version
CString strIdentityName(*m_strArrayIdentityName.GetAt(0));
int i = strIdentityName.Find(ACSPOLICYTYPE_DELIMITER);
if(i != -1)
{
*pStrOffset = i+1;
strIdentityName = strIdentityName.Left(i);
}
return _ttoi(strIdentityName);
};
int GetIdentityType(CString& Str) const // return -1, of the type is not recognized, or IdentityName doesn't exist
{
int Offset;
int Id = GetIdentityType(&Offset);
if(Id != -1)
Str = m_strArrayIdentityName[0]->Mid(Offset);
return Id;
}
bool IsConflictInContainer();
void InvalidateConflictState();
bool IsConflictWith(const CACSPolicyElement& policy)
{
// disabled
if(m_dwServiceType == ACS_SERVICETYPE_DISABLED || policy.m_dwServiceType == ACS_SERVICETYPE_DISABLED)
return false;
if(policy.m_strArrayIdentityName.GetSize() == 0 || m_strArrayIdentityName.GetSize() ==0)
return false;
if(m_dwServiceType != policy.m_dwServiceType)
return false;
if((m_dwDirection & policy.m_dwDirection) == 0)
return false;
if(m_strArrayIdentityName[(INT_PTR)0]->CompareNoCase(*policy.m_strArrayIdentityName[0]) != 0)
return false;
return true;
};
bool IsServiceTypeDisabled()
{
return (m_dwServiceType == ACS_SERVICETYPE_DISABLED);
};
// ===========================================
// get the data memebers
STDMETHOD(GetString)(CString& str, int nCol);
BOOL m_bUseName_NewPolicy;
protected:
static CString m_strDirectionSend;
static CString m_strDirectionReceive;
static CString m_strDirectionBoth;
static CString m_strServiceTypeAll;
static CString m_strServiceTypeBestEffort;
static CString m_strServiceTypeControlledLoad;
static CString m_strServiceTypeGuaranteedService;
static CString m_strServiceTypeDisabled;
static CString m_strDefaultUser;
static CString m_strUnknownUser;
static CDSAttributeInfo m_aPolicyAttributeInfo[];
CDSAttribute m_aAttributes[__ACS_PAI_COUNT];
};
///////////////////////////////////////////////////////////////////////////////
//
// CACSPolicyContainer
//
class CACSPolicyContainer : public CACSContainerObject<CACSPolicyElement>
{
public:
bool IsConflictWithExisting(CACSPolicyElement* pPolicy)
// NO REF COUNT CHANGE
{
std::list<CDSObject*>::iterator i;
bool bConflict = false;
CACSPolicyElement* pExisting = NULL;
for(i = m_listChildren.begin(); !bConflict && i != m_listChildren.end(); i++)
{
pExisting = dynamic_cast<CACSPolicyElement*>(*i);
bConflict = ((pExisting != pPolicy) && pExisting->IsConflictWith(*pPolicy));
}
return bConflict;
};
// return # of conflict, this is always even number
UINT SetChildrenConflictState()
{
std::list<CDSObject*>::iterator i;
CACSPolicyElement* pSubject = NULL;
UINT count = 0;
for(i = m_listChildren.begin(); i != m_listChildren.end(); i++)
{
pSubject = dynamic_cast<CACSPolicyElement*>(*i);
ASSERT(pSubject);
DWORD state = pSubject->GetState();
if(IsConflictWithExisting(pSubject))
{
count++;
state = (state | ACSDATA_STATE_CONFLICT);
}
else
{
state = (state & (~ACSDATA_STATE_CONFLICT));
}
if(pSubject->IsServiceTypeDisabled())
{
state = (state | ACSDATA_STATE_DISABLED);
}
else
{
state = (state & (~ACSDATA_STATE_DISABLED));
}
pSubject->SetState(state);
}
return count;
};
};
///////////////////////////////////////////////////////////////////////////////
//
// CACSGlobalObject
//
class CACSGlobalObject : public CACSPolicyContainer
{
public:
// load from DS -- derived need to override, when need to load data
STDMETHOD(Open)();
STDMETHOD(OnOpen)();
UINT m_nOpenErrorId;
CString m_strDomainName;
};
///////////////////////////////////////////////////////////////////////////////
//
// CACSGlobalObject
//
class CACSSubnetsObject : public CACSContainerObject<CDSObject>
{
public:
// load from DS -- derived need to override, when need to load data
STDMETHOD(Open)();
};
///////////////////////////////////////////////////////////////////////////////
//
// CACSSubnetConfig : subnet in DS is still a folder which is capable of
// holding config object, users folder and profiles holder,
// the class defined here is the config object contained in
// subnet object
//
enum ACS_SUBNET_CONFIG_ATTRIBUTE_ID {
ACS_SCAI_INVALID = 0 ,
ACS_SCAI_ALLOCABLERSVPBW,
ACS_SCAI_MAXPEAKBW,
ACS_SCAI_ENABLERSVPMESSAGELOGGING,
ACS_SCAI_EVENTLOGLEVEL,
ACS_SCAI_ENABLEACSSERVICE,
ACS_SCAI_MAX_PF_TOKENRATE,
ACS_SCAI_MAX_PF_PEAKBW,
ACS_SCAI_MAX_PF_DURATION,
ACS_SCAI_RSVPLOGFILESLOCATION,
ACS_SCAI_DESCRIPTION,
ACS_SCAI_MAXNOOFLOGFILES,
ACS_SCAI_MAXSIZEOFRSVPLOGFILE,
ACS_SCAI_DSBMPRIORITY,
ACS_SCAI_DSBMREFRESH,
ACS_SCAI_DSBMDEADTIME,
ACS_SCAI_CACHETIMEOUT,
ACS_SCAI_NONRESERVEDTXLIMIT,
// accounting -- added by WeiJiang 2/16/98
ACS_SCAI_ENABLERSVPMESSAGEACCOUNTING,
ACS_SCAI_RSVPACCOUNTINGFILESLOCATION,
ACS_SCAI_MAXNOOFACCOUNTINGFILES,
ACS_SCAI_MAXSIZEOFRSVPACCOUNTINGFILE,
// server list
ACS_SCAI_SERVERLIST,
// the total count of the elementas
__ACS_SCAI_COUNT
};
// bit flags for the attributes
#define ACS_SCAF_ALLOCABLERSVPBW 0x00000001
#define ACS_SCAF_MAXPEAKBW 0x00000002
#define ACS_SCAF_ENABLERSVPMESSAGELOGGING 0x00000004
#define ACS_SCAF_EVENTLOGLEVEL 0x00000008
#define ACS_SCAF_ENABLEACSSERVICE 0x00000010
#define ACS_SCAF_MAX_PF_TOKENRATE 0x00000020
#define ACS_SCAF_MAX_PF_PEAKBW 0x00000040
#define ACS_SCAF_MAX_PF_DURATION 0x00000080
#define ACS_SCAF_DESCRIPTION 0x00000100
#define ACS_SCAF_RSVPLOGFILESLOCATION 0x00000200
#define ACS_SCAF_MAXNOOFLOGFILES 0x00000400
#define ACS_SCAF_MAXSIZEOFRSVPLOGFILE 0x00000800
#define ACS_SCAF_DSBMPRIORITY 0x00001000
#define ACS_SCAF_DSBMREFRESH 0x00002000
#define ACS_SCAF_DSBMDEADTIME 0x00004000
#define ACS_SCAF_CACHETIMEOUT 0x00008000
#define ACS_SCAF_NONRESERVEDTXLIMIT 0x00010000
// accounting -- added by WeiJiang 2/16/98
#define ACS_SCAF_ENABLERSVPMESSAGEACCOUNTING 0x00020000
#define ACS_SCAF_RSVPACCOUNTINGFILESLOCATION 0x00040000
#define ACS_SCAF_MAXNOOFACCOUNTINGFILES 0x00080000
#define ACS_SCAF_MAXSIZEOFRSVPACCOUNTINGFILE 0x00100000
//Server list
#define ACS_SCAF_SERVERLIST 0x00200000
class CACSSubnetConfig : public CDSObject
{
friend class CPgGeneral;
friend class CPgLogging;
friend class CPgSBM;
friend class CPgAccounting;
friend class CPgServers;
public:
CACSSubnetConfig() : CDSObject(true)
{
void* pVoid;
CDSAttributeInfo* pInfo = m_aSubnetAttributeInfo;
int count = 0;
while(pInfo && pInfo->id)
{
m_aAttributes[count].pInfo = pInfo;
switch(pInfo->id)
{
case ACS_SCAI_ALLOCABLERSVPBW: pVoid = (void*)&m_ddALLOCABLERSVPBW; break;
case ACS_SCAI_MAXPEAKBW: pVoid = (void*)&m_ddMAXPEAKBW; break;
case ACS_SCAI_ENABLERSVPMESSAGELOGGING: pVoid = (void*)&m_bENABLERSVPMESSAGELOGGING; break;
case ACS_SCAI_EVENTLOGLEVEL: pVoid = (void*)&m_dwEVENTLOGLEVEL; break;
case ACS_SCAI_ENABLEACSSERVICE: pVoid = (void*)&m_bENABLEACSSERVICE; break;
case ACS_SCAI_MAX_PF_TOKENRATE: pVoid = (void*)&m_ddMAX_PF_TOKENRATE; break;
case ACS_SCAI_MAX_PF_PEAKBW: pVoid = (void*)&m_ddMAX_PF_PEAKBW; break;
case ACS_SCAI_MAX_PF_DURATION: pVoid = (void*)&m_dwMAX_PF_DURATION; break;
case ACS_SCAI_RSVPLOGFILESLOCATION: pVoid = (void*)&m_strRSVPLOGFILESLOCATION; break;
case ACS_SCAI_DESCRIPTION: pVoid = (void*)&m_strDESCRIPTION; break;
case ACS_SCAI_MAXNOOFLOGFILES: pVoid = (void*)&m_dwMAXNOOFLOGFILES; break;
case ACS_SCAI_MAXSIZEOFRSVPLOGFILE: pVoid = (void*)&m_dwMAXSIZEOFRSVPLOGFILE; break;
case ACS_SCAI_DSBMPRIORITY: pVoid = (void*)&m_dwDSBMPRIORITY; break;
case ACS_SCAI_DSBMREFRESH: pVoid = (void*)&m_dwDSBMREFRESH; break;
case ACS_SCAI_DSBMDEADTIME: pVoid = (void*)&m_dwDSBMDEADTIME; break;
case ACS_SCAI_CACHETIMEOUT: pVoid = (void*)&m_dwCACHETIMEOUT; break;
case ACS_SCAI_NONRESERVEDTXLIMIT: pVoid = (void*)&m_ddNONRESERVEDTXLIMIT; break;
// accounting added by WeiJiang 2/16/98
case ACS_SCAI_ENABLERSVPMESSAGEACCOUNTING: pVoid = (void*)&m_bENABLERSVPMESSAGEACCOUNTING; break;
case ACS_SCAI_RSVPACCOUNTINGFILESLOCATION: pVoid = (void*)&m_strRSVPACCOUNTINGFILESLOCATION; break;
case ACS_SCAI_MAXNOOFACCOUNTINGFILES: pVoid = (void*)&m_dwMAXNOOFACCOUNTINGFILES; break;
case ACS_SCAI_MAXSIZEOFRSVPACCOUNTINGFILE: pVoid = (void*)&m_dwMAXSIZEOFRSVPACCOUNTINGFILE; break;
case ACS_SCAI_SERVERLIST: pVoid = (void*)&m_strArrayServerList; break;
default: ASSERT(0); break; // this should NOT happen
}
m_aAttributes[count++].pBuffer = pVoid;
pInfo++;
}
m_aAttributes[count].pInfo = 0;
m_aAttributes[count].pBuffer = 0;
};
virtual CDSAttribute* GetAttributes() { return &(m_aAttributes[0]);};
// ===========================================
// get the data memebers
STDMETHOD(GetString)(CString& str, int nCol);
protected:
static CDSAttributeInfo m_aSubnetAttributeInfo[];
CDSAttribute m_aAttributes[__ACS_SCAI_COUNT];
//===================================================
// data member
CString m_strDescription;
ADS_LARGE_INTEGER m_ddALLOCABLERSVPBW;
ADS_LARGE_INTEGER m_ddMAXPEAKBW;
ADS_BOOLEAN m_bENABLERSVPMESSAGELOGGING;
ADS_INTEGER m_dwEVENTLOGLEVEL;
ADS_BOOLEAN m_bENABLEACSSERVICE;
ADS_LARGE_INTEGER m_ddMAX_PF_TOKENRATE;
ADS_LARGE_INTEGER m_ddMAX_PF_PEAKBW;
ADS_INTEGER m_dwMAX_PF_DURATION;
CString m_strRSVPLOGFILESLOCATION;
CString m_strDESCRIPTION;
ADS_INTEGER m_dwMAXNOOFLOGFILES;
ADS_INTEGER m_dwMAXSIZEOFRSVPLOGFILE;
ADS_INTEGER m_dwDSBMPRIORITY;
ADS_INTEGER m_dwDSBMREFRESH;
ADS_INTEGER m_dwDSBMDEADTIME;
ADS_INTEGER m_dwCACHETIMEOUT;
ADS_LARGE_INTEGER m_ddNONRESERVEDTXLIMIT;
// accounting -- added by WeiJiang 2/16/98
ADS_BOOLEAN m_bENABLERSVPMESSAGEACCOUNTING;
CString m_strRSVPACCOUNTINGFILESLOCATION;
ADS_INTEGER m_dwMAXNOOFACCOUNTINGFILES;
ADS_INTEGER m_dwMAXSIZEOFRSVPACCOUNTINGFILE;
// Server list
CStrArray m_strArrayServerList;
};
//===============================================================
// subnet service limit
//
// bit flags for the attributes
#define ACS_SSLAF_ALLOCABLERSVPBW 0x00000001
#define ACS_SSLAF_MAXPEAKBW 0x00000002
#define ACS_SSLAF_MAX_PF_TOKENRATE 0x00000004
#define ACS_SSLAF_MAX_PF_PEAKBW 0x00000008
#define ACS_SSLAF_SERVICETYPE 0x00000010
enum ACS_SUBNET_SERVICE_LIMITS_ATTRIBUTE_ID {
ACS_SSLAI_INVALID = 0 ,
ACS_SSLAI_ALLOCABLERSVPBW,
ACS_SSLAI_MAXPEAKBW,
ACS_SSLAI_MAX_PF_TOKENRATE,
ACS_SSLAI_MAX_PF_PEAKBW,
ACS_SSLAI_SERVICETYPE ,
// the total count of the elementas
__ACS_SSLAI_COUNT
};
class CACSSubnetServiceLimits : public CDSObject
{
public:
CACSSubnetServiceLimits() : CDSObject(true)
{
void* pVoid;
CDSAttributeInfo* pInfo = m_aSubnetServiceLimitsAttributeInfo;
int count = 0;
while(pInfo && pInfo->id)
{
m_aAttributes[count].pInfo = pInfo;
switch(pInfo->id)
{
case ACS_SSLAI_ALLOCABLERSVPBW: pVoid = (void*)&m_ddALLOCABLERSVPBW; break;
case ACS_SSLAI_MAXPEAKBW: pVoid = (void*)&m_ddMAXPEAKBW; break;
case ACS_SSLAI_MAX_PF_TOKENRATE: pVoid = (void*)&m_ddMAX_PF_TOKENRATE; break;
case ACS_SSLAI_MAX_PF_PEAKBW: pVoid = (void*)&m_ddMAX_PF_PEAKBW; break;
case ACS_SSLAI_SERVICETYPE: pVoid = (void*)&m_dwServiceType; break;
default: ASSERT(0); break; // this should NOT happen
}
m_aAttributes[count++].pBuffer = pVoid;
pInfo++;
}
m_aAttributes[count].pInfo = 0;
m_aAttributes[count].pBuffer = 0;
};
virtual CDSAttribute* GetAttributes() { return &(m_aAttributes[0]);};
// ===========================================
// get the data memebers
STDMETHOD(GetString)(CString& str, int nCol)
{
switch(nCol)
{
case 0: // name
// inteprete name based on service type
//
break;
case 1: // per flow data
break;
case 2: // per flow peak
break;
case 3: // aggre data
break;
case 4: // aggre peak
break;
}
return S_OK;
};
protected:
static CDSAttributeInfo m_aSubnetServiceLimitsAttributeInfo[];
CDSAttribute m_aAttributes[__ACS_SSLAI_COUNT];
public:
//===================================================
// data member
ADS_LARGE_INTEGER m_ddALLOCABLERSVPBW;
ADS_LARGE_INTEGER m_ddMAXPEAKBW;
ADS_LARGE_INTEGER m_ddMAX_PF_TOKENRATE;
ADS_LARGE_INTEGER m_ddMAX_PF_PEAKBW;
ADS_INTEGER m_dwServiceType;
};
class CACSSubnetLimitsContainer : public CACSContainerObject<CACSSubnetServiceLimits>
{
public:
CACSSubnetLimitsContainer() : CACSContainerObject<CACSSubnetServiceLimits>(true)
{};
};
///////////////////////////////////////////////////////////////////////////////
//
// CACSSubnetObject
//
class CACSSubnetObject : public CACSPolicyContainer
{
public:
// delete the object from DS -- usually not override
STDMETHOD(Delete)()
{
HRESULT hr = CACSPolicyContainer::Delete();
CHECK_HR(hr);
m_spConfigObject.Release();
L_ERR:
return hr;
};
// called after the object is open,
// m_pIObject, m_pIContainer are available to use
// read attributes from DS should be done in this function
STDMETHOD(OnOpen)()
{
HRESULT hr = S_OK;
if(m_spConfigObject.p == NULL)
{
CComObject<CACSSubnetConfig>* pConfig;
CHECK_HR(hr = CComObject<CACSSubnetConfig>::CreateInstance(&pConfig));
ASSERT(pConfig);
m_spConfigObject = pConfig;
}
if(m_spSubnetLimitsContainer.p == NULL)
{
CComObject<CACSSubnetLimitsContainer>* pCont;
CHECK_HR(hr = CComObject<CACSSubnetLimitsContainer>::CreateInstance(&pCont));
ASSERT(pCont);
m_spSubnetLimitsContainer = pCont;
}
if (IfNewCreated())
{
// create policy for default user
CComObject<CACSPolicyElement>* pPolicy = NULL;
CComPtr<CACSPolicyElement> spPolicy;
// create the object in DS
CHECK_HR(hr = CComObject<CACSPolicyElement>::CreateInstance(&pPolicy)); // ref == 0
spPolicy = pPolicy; // ref == 1
if((CACSPolicyElement*)spPolicy)
{
spPolicy->SetFlags(ATTR_FLAG_SAVE, spPolicy->SetDefault(), true);
CHECK_HR(hr = spPolicy->Open(this, ACS_CLS_POLICY, ACSPOLICY_DEFAULT, true, true));
CHECK_HR(hr = spPolicy->Close());
}
// create policy for unknown user
// create the object in DS
CHECK_HR(hr = CComObject<CACSPolicyElement>::CreateInstance(&pPolicy)); // ref == 0
spPolicy = pPolicy; // ref == 1
if((CACSPolicyElement*)spPolicy)
{
spPolicy->SetFlags(ATTR_FLAG_SAVE, spPolicy->SetUnknown(), true);
CHECK_HR(hr = spPolicy->Open(this, ACS_CLS_POLICY, ACSPOLICY_UNKNOWN, true, true));
CHECK_HR(hr = spPolicy->Close());
}
// config object
CHECK_HR(hr = m_spConfigObject->Open(this, ACS_CLS_SUBNETCONFIG, ACS_NAME_SUBNETCONFIG, true, true));
// limits container object
CHECK_HR(hr = m_spSubnetLimitsContainer->Open(this, ACS_CLS_CONTAINER, ACS_NAME_SUBNETLIMITS, true, true));
// create default policies for the subnet
}
else
{
// config object
CHECK_HR(hr = m_spConfigObject->SetInfo(this, ACS_CLS_SUBNETCONFIG, ACS_NAME_SUBNETCONFIG));
#if 0 // fix bug 366384 1 D0707 johnmil a-leeb ACS: New snap-in not backward compatible with older subnets
// limits container object
CHECK_HR(hr = m_spLimitsContainer->SetInfo(this, ACS_CLS_CONTAINER, ACS_NAME_SUBNETLIMITS));
#else
// limits container object
CHECK_HR(hr = m_spSubnetLimitsContainer->Open(this, ACS_CLS_CONTAINER, ACS_NAME_SUBNETLIMITS, true, true));
#endif
}
L_ERR:
return hr;
};
// called before SetInfo is called to set the object
// m_pIObject, m_pIContainer are available to use
// write attributes to DS should be done in this function
STDMETHOD(OnSave)(DWORD dwAttrFlags)
{
if((CACSSubnetConfig*)m_spConfigObject) // if the subobject is open
return m_spConfigObject->Save(ATTR_FLAGS_ALL);
else
return S_OK;
};
HRESULT GetConfig(CACSSubnetConfig** ppConfig)
{
ASSERT(ppConfig);
*ppConfig = (CACSSubnetConfig*)m_spConfigObject;
if(*ppConfig) (*ppConfig)->AddRef();
return S_OK;
};
// Get service limits container object
HRESULT GetLimitsContainer( CACSSubnetLimitsContainer **ppContainer )
{
ASSERT(ppContainer);
*ppContainer = (CACSSubnetLimitsContainer*)m_spSubnetLimitsContainer;
if(*ppContainer) (*ppContainer)->AddRef();
return S_OK;
};
// ===========================================
// get the data memebers
STDMETHOD(GetString)(CString& str, int nCol);
protected:
CComPtr<CACSSubnetConfig> m_spConfigObject;
CComPtr<CACSSubnetLimitsContainer> m_spSubnetLimitsContainer;
};
///////////////////////////////////////////////////////////////////////////////
//
// CACSContainerObject
//
//
//+----------------------------------------------------------------------------
//
// Method: CACSContainerObject::ListChildren
//
// Synopsis: list children to the list, create the children name list
//
//-----------------------------------------------------------------------------
template <class T>
HRESULT CACSContainerObject<T>::ListChildren(std::list<T*>& children, BSTR clsName)
{
CComPtr<IEnumVARIANT> spEnum;
CComPtr<IADsContainer> spContainer;
CComPtr<IADs> spChild;
CComPtr<IDispatch> spDisp;
BSTR bstr = NULL;
HRESULT hr = S_OK;
VARIANT var;
CComPtr< CComObject<T> > spDSObj;
VariantInit(&var);
RemoveAllChildren(); // RemoveAllChildren from the existing list
if(!(IADs*)m_spIADs)
CHECK_HR(hr = Reopen());
CHECK_HR(hr = m_spIADs->QueryInterface(IID_IADsContainer, (void**)&spContainer));
CHECK_HR(hr = ADsBuildEnumerator(spContainer, &spEnum));
try{
VariantClear(&var);
while(S_OK == (hr = ADsEnumerateNext(spEnum, 1, &var, NULL)))
{
spDisp.Release();
spDisp = var.pdispVal;
spChild.Release(); // make sure spChild is NULL
CHECK_HR(hr = spDisp->QueryInterface(IID_IADs, (VOID **)&spChild));
// if this object is a profile object
if(clsName)
{
CHECK_HR(spChild->get_Class(&bstr));
if (0 != _wcsicmp(bstr, clsName))
{
SysFreeString(bstr);
continue;
}
SysFreeString(bstr);
}
// create the object
spDSObj.Release(); // make sure it's NULL
CHECK_HR(hr = CComObject<T>::CreateInstance(&spDSObj)); // with 0 reference count
spDSObj->AddRef();
CHECK_HR(hr = spDSObj->Attach(this, spChild));
// add to the children list,
spDSObj->AddRef();
children.push_back(spDSObj);
// register the child in the children list
CHECK_HR(hr = AddChild(spDSObj));
CHECK_HR(hr = spDSObj->Close());
VariantClear(&var);
}
}
catch(CMemoryException&)
{
CHECK_HR(hr = E_OUTOFMEMORY);
}
m_bListed = true;
hr = S_OK;
L_ERR:
return hr;
}
//////
#endif
/////////////////////////////////////////////