windows-nt/Source/XPSP1/NT/inetsrv/iis/admin/adsi/adsiis/cschema.cxx
2020-09-26 16:20:57 +08:00

3054 lines
70 KiB
C++

//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1996
//
// File: cschema.cxx
//
// Contents: Windows NT 4.0
//
//
// History: 01-09-98 sophiac Created.
//
//----------------------------------------------------------------------------
#include "iis.hxx"
#pragma hdrstop
#define PROP_RW 0x0000001
SCHEMAOBJPROPS g_pClassObjProps[] = {
{L"PrimaryInterface", IIS_SYNTAX_ID_STRING, CLASS_PRIMARY_INTERFACE},
{L"CLSID", IIS_SYNTAX_ID_STRING, CLASS_CLSID},
{L"OID", IIS_SYNTAX_ID_STRING, CLASS_OID},
{L"Abstract", IIS_SYNTAX_ID_BOOL, CLASS_ABSTRACT},
{L"Auxiliary", IIS_SYNTAX_ID_BOOL, CLASS_AUXILIARY},
{L"MandatoryProperties", IIS_SYNTAX_ID_STRING, CLASS_MAND_PROPERTIES},
{L"OptionalProperties", IIS_SYNTAX_ID_STRING, CLASS_OPT_PROPERTIES},
{L"NamingProperties", IIS_SYNTAX_ID_STRING, CLASS_NAMING_PROPERTIES},
{L"DerivedFrom", IIS_SYNTAX_ID_STRING, CLASS_DERIVEDFROM},
{L"AuxDerivedFrom", IIS_SYNTAX_ID_STRING, CLASS_AUX_DERIVEDFROM},
{L"PossibleSuperiors", IIS_SYNTAX_ID_STRING, CLASS_POSS_SUPERIORS},
{L"Containment", IIS_SYNTAX_ID_STRING, CLASS_CONTAINMENT},
{L"Container", IIS_SYNTAX_ID_BOOL, CLASS_CONTAINER},
{L"HelpFileName", IIS_SYNTAX_ID_STRING, CLASS_HELPFILENAME},
{L"HelpFileContext", IIS_SYNTAX_ID_DWORD, CLASS_HELPFILECONTEXT}
};
SCHEMAOBJPROPS g_pPropertyObjProps[] = {
{L"OID", IIS_SYNTAX_ID_STRING, PROP_OID},
{L"Syntax", IIS_SYNTAX_ID_STRING, PROP_SYNTAX},
{L"MaxRange", IIS_SYNTAX_ID_DWORD, PROP_MAXRANGE},
{L"MinRange", IIS_SYNTAX_ID_DWORD, PROP_MINRANGE},
{L"MultiValued", IIS_SYNTAX_ID_BOOL, PROP_MULTIVALUED},
{L"PropName", IIS_SYNTAX_ID_STRING, PROP_PROPNAME},
{L"MetaId", IIS_SYNTAX_ID_DWORD, PROP_METAID},
{L"UserType", IIS_SYNTAX_ID_DWORD, PROP_USERTYPE},
{L"AllAttributes", IIS_SYNTAX_ID_DWORD, PROP_ALLATTRIBUTES},
{L"Inherit", IIS_SYNTAX_ID_BOOL, PROP_INHERIT},
{L"PartialPath", IIS_SYNTAX_ID_BOOL, PROP_PARTIALPATH},
{L"Secure", IIS_SYNTAX_ID_BOOL, PROP_SECURE},
{L"Reference", IIS_SYNTAX_ID_BOOL, PROP_REFERENCE},
{L"Volatile", IIS_SYNTAX_ID_BOOL, PROP_VOLATILE},
{L"Isinherit", IIS_SYNTAX_ID_BOOL, PROP_ISINHERIT},
{L"InsertPath", IIS_SYNTAX_ID_BOOL, PROP_INSERTPATH},
{L"Default", IIS_SYNTAX_ID_STRING_DWORD, PROP_DEFAULT}
};
DWORD g_cPropertyObjProps (sizeof(g_pPropertyObjProps)/sizeof(SCHEMAOBJPROPS));
DWORD g_cClassObjProps (sizeof(g_pClassObjProps)/sizeof(SCHEMAOBJPROPS));
/******************************************************************/
/* Class CIISClass
/******************************************************************/
DEFINE_IDispatch_Implementation(CIISClass)
DEFINE_IADs_Implementation(CIISClass)
CIISClass::CIISClass()
: _pDispMgr( NULL ),
_bstrCLSID( NULL ),
_bstrOID( NULL ),
_bstrPrimaryInterface( NULL ),
_fAbstract( FALSE ),
_fContainer( FALSE ),
_bstrHelpFileName( NULL ),
_lHelpFileContext( 0 ),
_bExistClass(FALSE),
_pSchema(NULL),
_pszServerName(NULL),
_pszClassName(NULL),
_pAdminBase(NULL)
{
VariantInit( &_vMandatoryProperties );
VariantInit( &_vOptionalProperties );
VariantInit( &_vPossSuperiors );
VariantInit( &_vContainment );
ENLIST_TRACKING(CIISClass);
}
CIISClass::~CIISClass()
{
if ( _bstrCLSID ) {
ADsFreeString( _bstrCLSID );
}
if ( _bstrOID ) {
ADsFreeString( _bstrOID );
}
if ( _bstrPrimaryInterface ) {
ADsFreeString( _bstrPrimaryInterface );
}
if ( _bstrHelpFileName ) {
ADsFreeString( _bstrHelpFileName );
}
if (_pszServerName) {
FreeADsStr(_pszServerName);
}
if (_pszClassName) {
FreeADsStr(_pszClassName);
}
VariantClear( &_vMandatoryProperties );
VariantClear( &_vOptionalProperties );
VariantClear( &_vPossSuperiors );
VariantClear( &_vContainment );
delete _pDispMgr;
}
HRESULT
CIISClass::CreateClass(
BSTR bstrParent,
BSTR bstrRelative,
DWORD dwObjectState,
REFIID riid,
void **ppvObj
)
{
CIISClass FAR *pClass = NULL;
HRESULT hr = S_OK;
BSTR bstrTmp = NULL;
CLASSINFO *pClassInfo;
OBJECTINFO ObjectInfo;
POBJECTINFO pObjectInfo = &ObjectInfo;
CLexer Lexer(bstrParent);
memset(pObjectInfo, 0, sizeof(OBJECTINFO));
hr = AllocateClassObject( &pClass );
BAIL_ON_FAILURE(hr);
hr = ADsObject(&Lexer, pObjectInfo);
BAIL_ON_FAILURE(hr);
hr = InitServerInfo(pObjectInfo->TreeName,
&pClass->_pAdminBase,
&pClass->_pSchema);
BAIL_ON_FAILURE(hr);
pClass->_pszServerName = AllocADsStr(pObjectInfo->TreeName);
if (!pClass->_pszServerName) {
hr = E_OUTOFMEMORY;
BAIL_ON_FAILURE(hr);
}
pClass->_pszClassName = AllocADsStr(bstrRelative);
if (!pClass->_pszClassName) {
hr = E_OUTOFMEMORY;
BAIL_ON_FAILURE(hr);
}
pClassInfo = pClass->_pSchema->GetClassInfo(bstrRelative);
//
// an existing class
//
if (pClassInfo) {
pClass->_bExistClass = TRUE;
pClass->_lHelpFileContext = pClassInfo->lHelpFileContext;
pClass->_fContainer = (VARIANT_BOOL)pClassInfo->fContainer;
pClass->_fAbstract = (VARIANT_BOOL)pClassInfo->fAbstract;
if (pClassInfo->pPrimaryInterfaceGUID) {
hr = StringFromCLSID( (REFCLSID) *(pClassInfo->pPrimaryInterfaceGUID),
&bstrTmp );
BAIL_ON_FAILURE(hr);
hr = ADsAllocString( bstrTmp,
&pClass->_bstrPrimaryInterface);
BAIL_ON_FAILURE(hr);
CoTaskMemFree(bstrTmp);
bstrTmp = NULL;
}
if (pClassInfo->pCLSID) {
hr = StringFromCLSID( (REFCLSID) *(pClassInfo->pCLSID),
&bstrTmp );
BAIL_ON_FAILURE(hr);
hr = ADsAllocString( bstrTmp,
&pClass->_bstrCLSID );
BAIL_ON_FAILURE(hr);
CoTaskMemFree(bstrTmp);
bstrTmp = NULL;
}
hr = ADsAllocString( pClassInfo->bstrOID, &pClass->_bstrOID);
BAIL_ON_FAILURE(hr);
hr = MakeVariantFromStringList( pClassInfo->bstrMandatoryProperties,
&(pClass->_vMandatoryProperties));
BAIL_ON_FAILURE(hr);
hr = MakeVariantFromStringList( pClassInfo->bstrOptionalProperties,
&(pClass->_vOptionalProperties));
BAIL_ON_FAILURE(hr);
hr = MakeVariantFromStringList( pClassInfo->bstrPossSuperiors,
&(pClass->_vPossSuperiors));
BAIL_ON_FAILURE(hr);
hr = MakeVariantFromStringList( pClassInfo->bstrContainment,
&(pClass->_vContainment));
BAIL_ON_FAILURE(hr);
hr = ADsAllocString(pClassInfo->bstrHelpFileName,
&pClass->_bstrHelpFileName);
BAIL_ON_FAILURE(hr);
}
hr = pClass->InitializeCoreObject(
bstrParent,
bstrRelative,
CLASS_CLASS_NAME,
NO_SCHEMA,
CLSID_IISClass,
dwObjectState );
BAIL_ON_FAILURE(hr);
hr = pClass->QueryInterface( riid, ppvObj );
BAIL_ON_FAILURE(hr);
pClass->Release();
FreeObjectInfo(pObjectInfo);
RRETURN(hr);
error:
if ( bstrTmp != NULL )
CoTaskMemFree(bstrTmp);
*ppvObj = NULL;
delete pClass;
FreeObjectInfo(pObjectInfo);
RRETURN(hr);
}
STDMETHODIMP
CIISClass::QueryInterface(REFIID iid, LPVOID FAR* ppv)
{
if (IsEqualIID(iid, IID_IUnknown))
{
*ppv = (IADsClass FAR * ) this;
}
else if (IsEqualIID(iid, IID_IDispatch))
{
*ppv = (IADs FAR *) this;
}
else if (IsEqualIID(iid, IID_IADs))
{
*ppv = (IADs FAR *) this;
}
else if (IsEqualIID(iid, IID_IADsClass))
{
*ppv = (IADsClass FAR *) this;
}
else
{
*ppv = NULL;
return E_NOINTERFACE;
}
AddRef();
return NOERROR;
}
/* IADs methods */
STDMETHODIMP
CIISClass::SetInfo(THIS)
{
HRESULT hr = S_OK;
if (GetObjectState() == ADS_OBJECT_UNBOUND) {
hr = IISCreateObject();
BAIL_ON_FAILURE(hr);
//
// If the create succeeded, set the object type to bound
//
SetObjectState(ADS_OBJECT_BOUND);
}
hr = IISSetObject();
BAIL_ON_FAILURE(hr);
error:
RRETURN(hr);
}
/* INTRINSA suppress=null_pointers, uninitialized */
HRESULT
CIISClass::IISSetObject()
{
HRESULT hr = S_OK;
METADATA_HANDLE hObjHandle = NULL;
PMETADATA_RECORD pMetaDataArray = NULL;
DWORD dwMDNumDataEntries = 0;
CLASSINFO ClassInfo;
LPBYTE pBuffer = NULL;
memset(&ClassInfo, 0, sizeof(CLASSINFO));
//
// Add SetObject functionality : sophiac
//
if (GetObjectState() == ADS_OBJECT_UNBOUND) {
hr = E_ADS_OBJECT_UNBOUND;
BAIL_ON_FAILURE(hr);
}
hr = OpenAdminBaseKey(
_pszServerName,
SCHEMA_CLASS_METABASE_PATH,
METADATA_PERMISSION_WRITE,
&_pAdminBase,
&hObjHandle
);
BAIL_ON_FAILURE(hr);
hr = MakeStringFromVariantArray(&_vMandatoryProperties, (LPBYTE*)&pBuffer);
BAIL_ON_FAILURE(hr);
hr = ValidateProperties((LPWSTR)pBuffer, TRUE);
BAIL_ON_FAILURE(hr);
hr = CheckDuplicateNames((LPWSTR)pBuffer);
BAIL_ON_FAILURE(hr);
ClassInfo.bstrMandatoryProperties = (BSTR)pBuffer;
pBuffer = NULL;
hr = MakeStringFromVariantArray(&_vOptionalProperties, (LPBYTE*)&pBuffer);
BAIL_ON_FAILURE(hr);
hr = ValidateProperties((LPWSTR)pBuffer, FALSE);
BAIL_ON_FAILURE(hr);
hr = CheckDuplicateNames((LPWSTR)pBuffer);
BAIL_ON_FAILURE(hr);
ClassInfo.bstrOptionalProperties = (BSTR)pBuffer;
pBuffer = NULL;
hr = MakeStringFromVariantArray(&_vContainment, (LPBYTE*)&pBuffer);
BAIL_ON_FAILURE(hr);
hr = ValidateClassNames((LPWSTR)pBuffer);
BAIL_ON_FAILURE(hr);
hr = CheckDuplicateNames((LPWSTR)pBuffer);
BAIL_ON_FAILURE(hr);
ClassInfo.bstrContainment = (BSTR)pBuffer;
pBuffer = NULL;
ClassInfo.fContainer = _fContainer;
//
// validate data
//
if ((ClassInfo.fContainer && !ClassInfo.bstrContainment) ||
(!ClassInfo.fContainer && ClassInfo.bstrContainment) ) {
hr = E_ADS_SCHEMA_VIOLATION;
BAIL_ON_FAILURE(hr);
}
// Things are okay, so reset the _v members just incase things have changed
hr = MakeVariantFromStringList( ClassInfo.bstrMandatoryProperties,
&(_vMandatoryProperties));
BAIL_ON_FAILURE(hr);
hr = MakeVariantFromStringList( ClassInfo.bstrOptionalProperties,
&(_vOptionalProperties));
BAIL_ON_FAILURE(hr);
hr = MakeVariantFromStringList( ClassInfo.bstrContainment,
&(_vContainment));
BAIL_ON_FAILURE(hr);
hr = IISMarshallClassProperties(
&ClassInfo,
&pMetaDataArray,
&dwMDNumDataEntries
);
BAIL_ON_FAILURE(hr);
hr = MetaBaseSetAllData(
_pAdminBase,
hObjHandle,
_pszClassName,
(PMETADATA_RECORD)pMetaDataArray,
dwMDNumDataEntries
);
BAIL_ON_FAILURE(hr);
//
// update schema cache
//
_pSchema->SetClassInfo(_pszClassName, &ClassInfo);
BAIL_ON_FAILURE(hr);
_bExistClass = TRUE;
error:
//
// if failed to create properties for new class, delete class node
//
if (FAILED(hr) && !_bExistClass && hObjHandle) {
MetaBaseDeleteObject(
_pAdminBase,
hObjHandle,
(LPWSTR)_pszClassName
);
}
if (ClassInfo.bstrOptionalProperties) {
FreeADsMem(ClassInfo.bstrOptionalProperties);
}
if (ClassInfo.bstrMandatoryProperties) {
FreeADsMem(ClassInfo.bstrMandatoryProperties);
}
if (ClassInfo.bstrContainment) {
FreeADsMem(ClassInfo.bstrContainment);
}
if (pBuffer) {
FreeADsMem(pBuffer);
}
if (pMetaDataArray) {
FreeADsMem(pMetaDataArray);
}
if (_pAdminBase && hObjHandle) {
CloseAdminBaseKey(_pAdminBase, hObjHandle);
}
RRETURN(hr);
}
HRESULT
CIISClass::IISCreateObject()
{
HRESULT hr = S_OK;
METADATA_HANDLE hObjHandle = NULL;
//
// Add CreateObject functionality : sophiac
//
hr = OpenAdminBaseKey(
_pszServerName,
SCHEMA_CLASS_METABASE_PATH,
METADATA_PERMISSION_WRITE,
&_pAdminBase,
&hObjHandle
);
BAIL_ON_FAILURE(hr);
//
// Pass in full path
//
hr = MetaBaseCreateObject(
_pAdminBase,
hObjHandle,
_pszClassName
);
BAIL_ON_FAILURE(hr);
error:
if (_pAdminBase && hObjHandle) {
CloseAdminBaseKey(_pAdminBase, hObjHandle);
}
RRETURN(hr);
}
STDMETHODIMP
CIISClass::GetInfo(THIS)
{
HRESULT hr = S_OK;
PCLASSINFO pClassInfo = NULL;
//
// free up memory first
//
VariantClear( &_vMandatoryProperties );
VariantClear( &_vOptionalProperties );
VariantClear( &_vContainment );
//
// get classinfo from schema cache
//
pClassInfo = _pSchema->GetClassInfo(_pszClassName);
if (pClassInfo) {
_fContainer = (VARIANT_BOOL)pClassInfo->fContainer;
hr = MakeVariantFromStringList( pClassInfo->bstrMandatoryProperties,
&_vMandatoryProperties);
BAIL_ON_FAILURE(hr);
hr = MakeVariantFromStringList( pClassInfo->bstrOptionalProperties,
&_vOptionalProperties);
BAIL_ON_FAILURE(hr);
hr = MakeVariantFromStringList( pClassInfo->bstrContainment,
&_vContainment);
BAIL_ON_FAILURE(hr);
}
error:
RRETURN(hr);
}
/* IADsClass methods */
STDMETHODIMP
CIISClass::Get(
THIS_ BSTR bstrName,
VARIANT FAR* pvProp
)
{
HRESULT hr = S_OK;
DWORD dwSyntaxId;
DWORD dwID;
//
// check if property is a supported property
//
hr = ValidateClassObjProps(bstrName, &dwSyntaxId, &dwID);
BAIL_ON_FAILURE(hr);
switch(dwID) {
case CLASS_OPT_PROPERTIES:
hr = get_OptionalProperties(pvProp);
break;
case CLASS_CONTAINMENT:
hr = get_Containment(pvProp);
break;
case CLASS_CONTAINER:
pvProp->vt = VT_BOOL;
pvProp->boolVal = _fContainer? VARIANT_TRUE : VARIANT_FALSE;
break;
default:
hr = E_ADS_PROPERTY_NOT_SUPPORTED;
}
error:
RRETURN(hr);
}
HRESULT
CIISClass::Put(
THIS_ BSTR bstrName,
VARIANT vProp
)
{
HRESULT hr = S_OK;
DWORD dwSyntaxId = 0;
DWORD dwID;
VARIANT vVar;
//
// check if property is a supported property and
// loop up its syntax id
//
hr = ValidateClassObjProps(bstrName, &dwSyntaxId, &dwID);
BAIL_ON_FAILURE(hr);
VariantInit(&vVar);
VariantCopyInd(&vVar, &vProp);
//
// update both classinfo and member variables
//
switch(dwID) {
case CLASS_OPT_PROPERTIES:
if (vVar.vt != VT_EMPTY &&
!((V_VT(&vVar) & VT_VARIANT) && V_ISARRAY(&vVar))) {
hr = E_ADS_CANT_CONVERT_DATATYPE;
BAIL_ON_FAILURE(hr);
}
VariantCopy(&_vOptionalProperties, &vVar);
break;
case CLASS_CONTAINMENT:
if (vVar.vt != VT_EMPTY &&
!((V_VT(&vVar) & VT_VARIANT) && V_ISARRAY(&vVar))) {
hr = E_ADS_CANT_CONVERT_DATATYPE;
BAIL_ON_FAILURE(hr);
}
VariantCopy(&_vContainment, &vVar);
break;
case CLASS_CONTAINER:
hr = CheckVariantDataType(&vProp, VT_BOOL);
BAIL_ON_FAILURE(hr);
_fContainer = (vProp.boolVal == VARIANT_TRUE) ? TRUE : FALSE;
break;
default:
hr = E_ADS_PROPERTY_NOT_SUPPORTED;
}
error:
VariantClear(&vVar);
RRETURN(hr);
}
STDMETHODIMP
CIISClass::GetEx(
THIS_ BSTR bstrName,
VARIANT FAR* pvProp
)
{
HRESULT hr = S_OK;
//
// Get and GetEx are the same for class schema object
//
hr = Get(bstrName, pvProp);
RRETURN(hr);
}
STDMETHODIMP
CIISClass::PutEx(
THIS_ long lnControlCode,
BSTR bstrName,
VARIANT vProp
)
{
RRETURN(E_NOTIMPL);
}
HRESULT
CIISClass::ValidateProperties(
LPWSTR pszList,
BOOL bMandatory
)
{
WCHAR *pszNewList;
WCHAR szName[MAX_PATH];
LPWSTR ObjectList = (LPWSTR)pszList;
HRESULT hr;
if (pszList == NULL) RRETURN(S_OK);
// need to allocate +2 = 1 for null, 1 for extra comma
pszNewList = new WCHAR[wcslen(pszList)+2];
if (pszNewList == NULL) RRETURN(E_OUTOFMEMORY);
wcscpy(pszNewList, L"");
while ((ObjectList = grabProp(szName, ObjectList)) != NULL) {
if (*szName != L'\0') {
hr = _pSchema->ValidatePropertyName(szName);
if (hr == E_ADS_PROPERTY_NOT_SUPPORTED) {
hr = PropertyInMetabase(szName, bMandatory);
}
else {
// form the new list
wcscat(pszNewList, szName);
wcscat(pszNewList, L",");
}
BAIL_ON_FAILURE(hr); // if it's a legit bad name
}
}
// get rid of the last comma
pszNewList[wcslen(pszNewList) - 1] = 0;
wcscpy(pszList, pszNewList);
delete [] pszNewList;
RRETURN(S_OK);
error:
//
// return E_ADS_SCHEMA_VIOLATION if property not found in global list
//
delete [] pszNewList;
RRETURN(E_ADS_SCHEMA_VIOLATION);
}
HRESULT
CIISClass::PropertyInMetabase(
LPWSTR szPropName,
BOOL bMandatory
)
{
// Oops - somethings wrong. What do we do? Depends...
//
// Check to see if the bad property name exists in the associated list
// in the metabase.
//
// If so (case 1), then we are trying to SetInfo after having deleted a property from
// the schema - so just silently remove the name from metabase & the cached class.
//
// If not (case 2), we are trying to SetInfo w/ a bogus property name,
// so throw an exception.
HRESULT hr = E_ADS_PROPERTY_NOT_SUPPORTED;
CLASSINFO *pClassInfo;
LPWSTR ObjectList;
WCHAR szTestProp[MAX_PATH];
pClassInfo = _pSchema->GetClassInfo(_pszClassName);
if (pClassInfo == NULL) {
RRETURN(hr);
}
if (bMandatory == TRUE) {
ObjectList = pClassInfo->bstrMandatoryProperties;
}
else {
ObjectList = pClassInfo->bstrOptionalProperties;
}
while ((ObjectList = grabProp(szTestProp, ObjectList)) != NULL) {
if (wcscmp(szTestProp, szPropName) == 0) {
hr = S_OK; // clear the error - we'll fix it (case 1)
}
}
RRETURN(hr);
}
HRESULT
CIISClass::ValidateClassNames(
LPWSTR pszList
)
{
WCHAR szName[MAX_PATH];
LPWSTR ObjectList = (LPWSTR)pszList;
HRESULT hr;
while ((ObjectList = grabProp(szName, ObjectList)) != NULL) {
if (*szName != L'\0') {
hr = _pSchema->ValidateClassName(szName);
if (FAILED(hr)) {
if (_wcsicmp(szName, _pszClassName)) {
BAIL_ON_FAILURE(hr);
}
}
}
}
RRETURN(S_OK);
error:
//
// return E_ADS_SCHEMA_VIOLATION if classname not found in global list
//
RRETURN(E_ADS_SCHEMA_VIOLATION);
}
STDMETHODIMP
CIISClass::get_PrimaryInterface( THIS_ BSTR FAR *pbstrGUID )
{
RRETURN(E_NOTIMPL);
}
STDMETHODIMP
CIISClass::get_CLSID( THIS_ BSTR FAR *pbstrCLSID )
{
RRETURN(E_NOTIMPL);
}
STDMETHODIMP
CIISClass::put_CLSID( THIS_ BSTR bstrCLSID )
{
RRETURN(E_NOTIMPL);
}
STDMETHODIMP
CIISClass::get_OID( THIS_ BSTR FAR *pbstrOID )
{
RRETURN(E_NOTIMPL);
}
STDMETHODIMP
CIISClass::put_OID( THIS_ BSTR bstrOID )
{
RRETURN(E_NOTIMPL);
}
STDMETHODIMP
CIISClass::get_Abstract( THIS_ VARIANT_BOOL FAR *pfAbstract )
{
RRETURN(E_NOTIMPL);
}
STDMETHODIMP
CIISClass::put_Abstract( THIS_ VARIANT_BOOL fAbstract )
{
RRETURN(E_NOTIMPL);
}
STDMETHODIMP
CIISClass::get_Auxiliary( THIS_ VARIANT_BOOL FAR *pfAuxiliary)
{
RRETURN(E_NOTIMPL);
}
STDMETHODIMP
CIISClass::put_Auxiliary( THIS_ VARIANT_BOOL fAuxiliary )
{
RRETURN(E_NOTIMPL);
}
STDMETHODIMP
CIISClass::get_NamingProperties( THIS_ VARIANT FAR *retval )
{
RRETURN(E_NOTIMPL);
}
STDMETHODIMP
CIISClass::put_NamingProperties( THIS_ VARIANT vNamingProperties )
{
RRETURN(E_NOTIMPL);
}
STDMETHODIMP
CIISClass::get_MandatoryProperties( THIS_ VARIANT FAR *retval )
{
if ( !retval )
RRETURN(E_ADS_BAD_PARAMETER);
VariantInit( retval );
RRETURN(VariantCopy(retval, &_vMandatoryProperties));
}
STDMETHODIMP
CIISClass::put_MandatoryProperties( THIS_ VARIANT vMandatoryProperties )
{
RRETURN(E_NOTIMPL);
}
STDMETHODIMP
CIISClass::get_OptionalProperties( THIS_ VARIANT FAR *retval )
{
if ( !retval )
RRETURN(E_ADS_BAD_PARAMETER);
VariantInit( retval );
RRETURN(VariantCopy(retval, &_vOptionalProperties));
}
STDMETHODIMP
CIISClass::put_OptionalProperties( THIS_ VARIANT vOptionalProperties )
{
HRESULT hr = put_VARIANT_Property( this, TEXT("OptionalProperties"),
vOptionalProperties );
if ( hr == E_ADS_CANT_CONVERT_DATATYPE )
{
hr = E_NOTIMPL;
}
RRETURN(hr);
}
STDMETHODIMP
CIISClass::get_DerivedFrom( THIS_ VARIANT FAR *pvDerivedFrom )
{
RRETURN(E_NOTIMPL);
}
STDMETHODIMP
CIISClass::put_DerivedFrom( THIS_ VARIANT vDerivedFrom )
{
RRETURN(E_NOTIMPL);
}
STDMETHODIMP
CIISClass::get_AuxDerivedFrom( THIS_ VARIANT FAR *pvAuxDerivedFrom )
{
RRETURN(E_NOTIMPL);
}
STDMETHODIMP
CIISClass::put_AuxDerivedFrom( THIS_ VARIANT vAuxDerivedFrom )
{
RRETURN(E_NOTIMPL);
}
STDMETHODIMP
CIISClass::get_PossibleSuperiors( THIS_ VARIANT FAR *pvPossSuperiors )
{
RRETURN(E_NOTIMPL);
}
STDMETHODIMP
CIISClass::put_PossibleSuperiors( THIS_ VARIANT vPossSuperiors )
{
RRETURN(E_NOTIMPL);
}
STDMETHODIMP
CIISClass::get_Containment( THIS_ VARIANT FAR *pvContainment )
{
if ( !pvContainment )
RRETURN(E_ADS_BAD_PARAMETER);
VariantInit( pvContainment );
RRETURN( VariantCopy( pvContainment, &_vContainment ));
}
STDMETHODIMP
CIISClass::put_Containment( THIS_ VARIANT vContainment )
{
HRESULT hr = put_VARIANT_Property( this, TEXT("Containment"),
vContainment );
if ( hr == E_ADS_CANT_CONVERT_DATATYPE )
{
hr = E_NOTIMPL;
}
RRETURN(hr);
}
STDMETHODIMP
CIISClass::get_Container( THIS_ VARIANT_BOOL FAR *pfContainer )
{
if ( !pfContainer )
RRETURN(E_ADS_BAD_PARAMETER);
*pfContainer = _fContainer? VARIANT_TRUE : VARIANT_FALSE;
RRETURN(S_OK);
}
STDMETHODIMP
CIISClass::put_Container( THIS_ VARIANT_BOOL fContainer )
{
HRESULT hr = put_VARIANT_BOOL_Property( this, TEXT("Container"),
fContainer );
RRETURN(hr);
}
STDMETHODIMP
CIISClass::get_HelpFileName( THIS_ BSTR FAR *pbstrHelpFileName )
{
RRETURN(E_NOTIMPL);
}
STDMETHODIMP
CIISClass::put_HelpFileName( THIS_ BSTR bstrHelpFile )
{
RRETURN(E_NOTIMPL);
}
STDMETHODIMP
CIISClass::get_HelpFileContext( THIS_ long FAR *plHelpContext )
{
RRETURN(E_NOTIMPL);
}
STDMETHODIMP
CIISClass::put_HelpFileContext( THIS_ long lHelpContext )
{
RRETURN(E_NOTIMPL);
}
STDMETHODIMP
CIISClass::Qualifiers(THIS_ IADsCollection FAR* FAR* ppQualifiers)
{
RRETURN(E_NOTIMPL);
}
HRESULT
CIISClass::AllocateClassObject(CIISClass FAR * FAR * ppClass)
{
CIISClass FAR *pClass = NULL;
CAggregatorDispMgr FAR *pDispMgr = NULL;
CPropertyCache FAR * pPropertyCache = NULL;
HRESULT hr = S_OK;
pClass = new CIISClass();
if ( pClass == NULL )
hr = E_OUTOFMEMORY;
BAIL_ON_FAILURE(hr);
pDispMgr = new CAggregatorDispMgr;
if ( pDispMgr == NULL )
hr = E_OUTOFMEMORY;
BAIL_ON_FAILURE(hr);
hr = pDispMgr->LoadTypeInfoEntry(
LIBID_ADs,
IID_IADs,
(IADs *) pClass,
DISPID_REGULAR );
BAIL_ON_FAILURE(hr);
hr = pDispMgr->LoadTypeInfoEntry(
LIBID_ADs,
IID_IADsClass,
(IADsClass *) pClass,
DISPID_REGULAR );
BAIL_ON_FAILURE(hr);
pClass->_pDispMgr = pDispMgr;
*ppClass = pClass;
RRETURN(hr);
error:
delete pDispMgr;
delete pClass;
RRETURN(hr);
}
/******************************************************************/
/* Class CIISProperty
/******************************************************************/
DEFINE_IDispatch_Implementation(CIISProperty)
DEFINE_IADs_Implementation(CIISProperty)
CIISProperty::CIISProperty()
: _pDispMgr( NULL ),
_bstrOID( NULL ),
_bstrSyntax( NULL ),
_lMaxRange( 0 ),
_lMinRange( 0 ),
_fMultiValued( FALSE ),
_lMetaId( 0 ),
_lUserType(IIS_MD_UT_SERVER ),
_lAllAttributes( 0),
_dwSyntaxId( IIS_SYNTAX_ID_DWORD ),
_dwFlags( PROP_RW ),
_dwMask( 0 ),
_dwPropID( 0 ),
_bExistProp(FALSE),
_pSchema(NULL),
_pszServerName(NULL),
_pszPropName(NULL),
_pAdminBase(NULL)
{
VariantInit(&_vDefault);
ADsAllocString(L"Integer", &_bstrSyntax);
ENLIST_TRACKING(CIISProperty);
}
CIISProperty::~CIISProperty()
{
if ( _bstrOID ) {
ADsFreeString( _bstrOID );
}
if ( _bstrSyntax ) {
ADsFreeString( _bstrSyntax );
}
if (_pszServerName) {
FreeADsStr(_pszServerName);
}
if (_pszPropName) {
FreeADsStr(_pszPropName);
}
VariantClear( &_vDefault );
delete _pDispMgr;
}
/* #pragma INTRINSA suppress=all */
HRESULT
CIISProperty::CreateProperty(
BSTR bstrParent,
BSTR bstrRelative,
DWORD dwObjectState,
REFIID riid,
void **ppvObj
)
{
CIISProperty FAR * pProperty = NULL;
HRESULT hr = S_OK;
PROPERTYINFO *pPropertyInfo;
OBJECTINFO ObjectInfo;
POBJECTINFO pObjectInfo = NULL;
CLexer Lexer(bstrParent);
hr = AllocatePropertyObject( &pProperty );
BAIL_ON_FAILURE(hr);
pObjectInfo = &ObjectInfo;
memset(pObjectInfo, 0, sizeof(OBJECTINFO));
hr = ADsObject(&Lexer, pObjectInfo);
BAIL_ON_FAILURE(hr);
hr = InitServerInfo(pObjectInfo->TreeName,
&pProperty->_pAdminBase,
&pProperty->_pSchema);
BAIL_ON_FAILURE(hr);
pProperty->_pszServerName = AllocADsStr(pObjectInfo->TreeName);
if (!pProperty->_pszServerName) {
hr = E_OUTOFMEMORY;
BAIL_ON_FAILURE(hr);
}
pProperty->_pszPropName = AllocADsStr(bstrRelative);
if (!pProperty->_pszPropName) {
hr = E_OUTOFMEMORY;
BAIL_ON_FAILURE(hr);
}
pPropertyInfo = pProperty->_pSchema->GetPropertyInfo(bstrRelative);
if (pPropertyInfo) {
LPWSTR pszSyntax;
pProperty->_bExistProp = TRUE;
hr = ADsAllocString( pPropertyInfo->bstrOID, &pProperty->_bstrOID);
BAIL_ON_FAILURE(hr);
pProperty->_lMaxRange = pPropertyInfo->lMaxRange;
pProperty->_lMinRange = pPropertyInfo->lMinRange;
pProperty->_fMultiValued = (VARIANT_BOOL)pPropertyInfo->fMultiValued;
pProperty->_lMetaId = pPropertyInfo->dwMetaID;
pProperty->_lUserType = pPropertyInfo->dwUserGroup;
pProperty->_lAllAttributes = pPropertyInfo->dwMetaFlags;
pProperty->_dwSyntaxId = pPropertyInfo->dwSyntaxId;
pProperty->_dwFlags = pPropertyInfo->dwFlags;
pProperty->_dwMask = pPropertyInfo->dwMask;
pProperty->_dwPropID = pPropertyInfo->dwPropID;
pszSyntax = SyntaxIdToString(pProperty->_dwSyntaxId);
hr = ADsAllocString(pszSyntax, &(pProperty->_bstrSyntax));
BAIL_ON_FAILURE(hr);
if (pPropertyInfo->dwSyntaxId == IIS_SYNTAX_ID_DWORD ||
pPropertyInfo->dwSyntaxId == IIS_SYNTAX_ID_IPSECLIST ||
pPropertyInfo->dwSyntaxId == IIS_SYNTAX_ID_NTACL ||
pPropertyInfo->dwSyntaxId == IIS_SYNTAX_ID_BINARY ) {
(pProperty->_vDefault).vt = VT_I4;
(pProperty->_vDefault).lVal = pPropertyInfo->dwDefault;
}
else if (pPropertyInfo->dwSyntaxId == IIS_SYNTAX_ID_BOOL ||
pPropertyInfo->dwSyntaxId == IIS_SYNTAX_ID_BOOL_BITMASK) {
(pProperty->_vDefault).vt = VT_BOOL;
(pProperty->_vDefault).boolVal =
pPropertyInfo->dwDefault ? VARIANT_TRUE : VARIANT_FALSE;
}
else if (pPropertyInfo->dwSyntaxId == IIS_SYNTAX_ID_MULTISZ ||
pPropertyInfo->dwSyntaxId == IIS_SYNTAX_ID_MIMEMAP ) {
LPWSTR pszStr = pPropertyInfo->szDefault;
hr = MakeVariantFromStringArray(NULL,
pszStr,
&(pProperty->_vDefault));
BAIL_ON_FAILURE(hr);
}
else {
(pProperty->_vDefault).vt = VT_BSTR;
hr = ADsAllocString( pPropertyInfo->szDefault,
&(pProperty->_vDefault.bstrVal));
BAIL_ON_FAILURE(hr);
}
}
hr = pProperty->InitializeCoreObject(
bstrParent,
bstrRelative,
PROPERTY_CLASS_NAME,
NO_SCHEMA,
CLSID_IISProperty,
dwObjectState );
BAIL_ON_FAILURE(hr);
hr = pProperty->QueryInterface( riid, ppvObj );
BAIL_ON_FAILURE(hr);
pProperty->Release();
FreeObjectInfo(pObjectInfo);
RRETURN(hr);
error:
*ppvObj = NULL;
delete pProperty;
FreeObjectInfo(pObjectInfo);
RRETURN(hr);
}
STDMETHODIMP
CIISProperty::QueryInterface(REFIID iid, LPVOID FAR* ppv)
{
if (IsEqualIID(iid, IID_IUnknown))
{
*ppv = (IADsProperty FAR *) this;
}
else if (IsEqualIID(iid, IID_IDispatch))
{
*ppv = (IADs FAR *) this;
}
else if (IsEqualIID(iid, IID_IADs))
{
*ppv = (IADs FAR *) this;
}
else if (IsEqualIID(iid, IID_IISSchemaObject))
{
*ppv = (IISSchemaObject FAR *) this;
}
else if (IsEqualIID(iid, IID_IADsProperty))
{
*ppv = (IADsProperty FAR *) this;
}
else
{
*ppv = NULL;
return E_NOINTERFACE;
}
AddRef();
return NOERROR;
}
/* IADs methods */
STDMETHODIMP
CIISProperty::SetInfo(THIS)
{
HRESULT hr = S_OK;
if (GetObjectState() == ADS_OBJECT_UNBOUND) {
//
// fill in all unset fields
//
// User set an explicit the MetaID for a new object
// we need to validate it.
if( _lMetaId != 0 &&
!IsMetaIdAvailable( _lMetaId )
)
{
return E_ADS_SCHEMA_VIOLATION;
}
if (!_bstrSyntax) {
LPWSTR pszSyntax;
pszSyntax = SyntaxIdToString(_dwSyntaxId);
hr = ADsAllocString(pszSyntax, &_bstrSyntax);
BAIL_ON_FAILURE(hr);
}
//
// If the create succeded, set the object type to bound
//
SetObjectState(ADS_OBJECT_BOUND);
}
hr = IISSetObject();
BAIL_ON_FAILURE(hr);
error:
RRETURN(hr);
}
HRESULT
CIISProperty::IISSetObject()
{
HRESULT hr = S_OK;
METADATA_HANDLE hObjHandle = NULL;
METADATA_RECORD mdr;
PropValue pv;
PROPERTYINFO PropertyInfo;
memset(&PropertyInfo, 0, sizeof(PROPERTYINFO));
//
// Add SetObject functionality : sophiac
//
if (GetObjectState() == ADS_OBJECT_UNBOUND) {
hr = E_ADS_OBJECT_UNBOUND;
BAIL_ON_FAILURE(hr);
}
//
// validate data
//
switch(_dwSyntaxId) {
case IIS_SYNTAX_ID_DWORD:
if (_vDefault.vt != VT_EMPTY) {
hr = CheckVariantDataType(&_vDefault, VT_I4);
if (FAILED(hr)) {
hr = E_ADS_SCHEMA_VIOLATION;
}
BAIL_ON_FAILURE(hr);
}
if (_lMaxRange < _lMinRange) {
hr = E_ADS_SCHEMA_VIOLATION;
BAIL_ON_FAILURE(hr);
}
break;
case IIS_SYNTAX_ID_BOOL:
case IIS_SYNTAX_ID_BOOL_BITMASK:
if ((_vDefault.vt != VT_EMPTY && _vDefault.vt != VT_BOOL) ||
_lMaxRange != 0 || _lMinRange != 0 ) {
hr = E_ADS_SCHEMA_VIOLATION;
BAIL_ON_FAILURE(hr);
}
break;
case IIS_SYNTAX_ID_STRING:
case IIS_SYNTAX_ID_EXPANDSZ:
if ((_vDefault.vt != VT_EMPTY && _vDefault.vt != VT_BSTR) ||
_lMaxRange != 0 || _lMinRange != 0 ) {
hr = E_ADS_SCHEMA_VIOLATION;
BAIL_ON_FAILURE(hr);
}
break;
case IIS_SYNTAX_ID_MIMEMAP:
case IIS_SYNTAX_ID_MULTISZ:
if ((_vDefault.vt != VT_EMPTY &&
_vDefault.vt != VT_VARIANT &&
!((V_VT(&_vDefault) & VT_VARIANT) && V_ISARRAY(&_vDefault))) ||
_lMaxRange != 0 || _lMinRange != 0 ) {
hr = E_ADS_SCHEMA_VIOLATION;
BAIL_ON_FAILURE(hr);
}
break;
case IIS_SYNTAX_ID_IPSECLIST:
if (_vDefault.vt != VT_EMPTY || _lMaxRange != 0 || _lMinRange != 0 ) {
hr = E_ADS_SCHEMA_VIOLATION;
BAIL_ON_FAILURE(hr);
}
break;
case IIS_SYNTAX_ID_BINARY:
case IIS_SYNTAX_ID_NTACL:
if (_vDefault.vt != VT_EMPTY || _lMaxRange != 0 || _lMinRange != 0 ) {
hr = E_ADS_SCHEMA_VIOLATION;
BAIL_ON_FAILURE(hr);
}
break;
default:
break;
}
//
// set property Default values
//
PropertyInfo.lMaxRange = _lMaxRange;
PropertyInfo.lMinRange = _lMinRange;
PropertyInfo.fMultiValued = _fMultiValued;
PropertyInfo.dwFlags = _dwFlags;
PropertyInfo.dwSyntaxId = _dwSyntaxId;
PropertyInfo.dwMask = _dwMask;
PropertyInfo.dwMetaFlags = _lAllAttributes;
PropertyInfo.dwUserGroup = _lUserType;
hr = ConvertDefaultValue(&_vDefault, &PropertyInfo);
BAIL_ON_FAILURE(hr);
hr = SetMetaID();
BAIL_ON_FAILURE(hr);
PropertyInfo.dwMetaID = _lMetaId;
PropertyInfo.dwPropID = _dwPropID;
hr = OpenAdminBaseKey(
_pszServerName,
SCHEMA_PROP_METABASE_PATH,
METADATA_PERMISSION_WRITE,
&_pAdminBase,
&hObjHandle
);
BAIL_ON_FAILURE(hr);
//
// set property name under Properties/Names
//
MD_SET_DATA_RECORD(&mdr,
(DWORD)_lMetaId,
METADATA_NO_ATTRIBUTES,
IIS_MD_UT_SERVER,
STRING_METADATA,
(wcslen((LPWSTR)_pszPropName)+1)*2,
(unsigned char *)_pszPropName);
hr = _pAdminBase->SetData(hObjHandle, L"Names", &mdr);
BAIL_ON_FAILURE(hr);
//
// set property attributes/types under Properties/Types
//
InitPropValue(&pv, &PropertyInfo);
mdr.dwMDDataType = BINARY_METADATA;
mdr.dwMDDataLen = sizeof(PropValue);
mdr.pbMDData = (unsigned char *)&pv;
hr = _pAdminBase->SetData(hObjHandle, L"Types", &mdr);
BAIL_ON_FAILURE(hr);
DataForSyntaxID(&PropertyInfo, &mdr);
hr = _pAdminBase->SetData(hObjHandle, L"Defaults", &mdr);
BAIL_ON_FAILURE(hr);
//
// update schema cache
//
hr = _pSchema->SetPropertyInfo(_pszPropName, &PropertyInfo);
BAIL_ON_FAILURE(hr);
_bExistProp = TRUE;
error:
if (PropertyInfo.szDefault) {
if (PropertyInfo.dwSyntaxId == IIS_SYNTAX_ID_STRING ||
PropertyInfo.dwSyntaxId == IIS_SYNTAX_ID_EXPANDSZ) {
FreeADsStr(PropertyInfo.szDefault );
}
else if (PropertyInfo.dwSyntaxId == IIS_SYNTAX_ID_MULTISZ) {
FreeADsMem(PropertyInfo.szDefault );
}
}
//
// if validation failed and new prop, delete class node
//
if (FAILED(hr) && !_bExistProp && hObjHandle) {
_pAdminBase->DeleteData(
hObjHandle,
(LPWSTR)L"Names",
_lMetaId,
ALL_METADATA
);
_pAdminBase->DeleteData(
hObjHandle,
(LPWSTR)L"Types",
_lMetaId,
ALL_METADATA
);
_pAdminBase->DeleteData(
hObjHandle,
(LPWSTR)L"Defaults",
_lMetaId,
ALL_METADATA
);
}
if (_pAdminBase && hObjHandle) {
CloseAdminBaseKey(_pAdminBase, hObjHandle);
}
RRETURN(hr);
}
STDMETHODIMP
CIISProperty::GetInfo(THIS)
{
HRESULT hr = S_OK;
PROPERTYINFO *pPropertyInfo = NULL;
//
// free up memory first
//
VariantClear( &_vDefault );
if ( _bstrOID ) {
ADsFreeString( _bstrOID );
}
if ( _bstrSyntax ) {
ADsFreeString( _bstrSyntax );
}
pPropertyInfo = _pSchema->GetPropertyInfo(_pszPropName);
if (pPropertyInfo) {
hr = ADsAllocString( pPropertyInfo->bstrOID, &_bstrOID);
BAIL_ON_FAILURE(hr);
hr = ADsAllocString( pPropertyInfo->bstrSyntax, &_bstrSyntax);
BAIL_ON_FAILURE(hr);
_lMaxRange = pPropertyInfo->lMaxRange;
_lMinRange = pPropertyInfo->lMinRange;
_fMultiValued = (VARIANT_BOOL)pPropertyInfo->fMultiValued;
_lMetaId = pPropertyInfo->dwMetaID;
_lUserType = pPropertyInfo->dwUserGroup;
_lAllAttributes = pPropertyInfo->dwMetaFlags;
_dwSyntaxId = pPropertyInfo->dwSyntaxId;
_dwFlags = pPropertyInfo->dwFlags;
_dwMask = pPropertyInfo->dwMask;
_dwPropID = pPropertyInfo->dwPropID;
if (pPropertyInfo->dwSyntaxId == IIS_SYNTAX_ID_DWORD ||
pPropertyInfo->dwSyntaxId == IIS_SYNTAX_ID_IPSECLIST ||
pPropertyInfo->dwSyntaxId == IIS_SYNTAX_ID_NTACL ||
pPropertyInfo->dwSyntaxId == IIS_SYNTAX_ID_BINARY ) {
_vDefault.vt = VT_I4;
_vDefault.lVal = pPropertyInfo->dwDefault;
}
else if (pPropertyInfo->dwSyntaxId == IIS_SYNTAX_ID_BOOL ||
pPropertyInfo->dwSyntaxId == IIS_SYNTAX_ID_BOOL_BITMASK) {
_vDefault.vt = VT_BOOL;
_vDefault.boolVal =
pPropertyInfo->dwDefault ? VARIANT_TRUE : VARIANT_FALSE;
}
else if (pPropertyInfo->dwSyntaxId == IIS_SYNTAX_ID_MULTISZ ||
pPropertyInfo->dwSyntaxId == IIS_SYNTAX_ID_MIMEMAP ) {
LPWSTR pszStr = pPropertyInfo->szDefault;
hr = MakeVariantFromStringArray(NULL,
pszStr,
&_vDefault);
BAIL_ON_FAILURE(hr);
}
else {
_vDefault.vt = VT_BSTR;
hr = ADsAllocString( pPropertyInfo->szDefault, &(_vDefault.bstrVal));
BAIL_ON_FAILURE(hr);
}
}
error:
RRETURN(hr);
}
STDMETHODIMP
CIISProperty::Get(
THIS_ BSTR bstrName,
VARIANT FAR* pvProp
)
{
HRESULT hr = S_OK;
DWORD dwSyntaxId;
DWORD dwID;
//
// check if property is a supported property
//
hr = ValidatePropertyObjProps(bstrName, &dwSyntaxId, &dwID);
BAIL_ON_FAILURE(hr);
switch(dwID) {
case PROP_SYNTAX:
pvProp->vt = VT_BSTR;
hr = ADsAllocString( _bstrSyntax, &pvProp->bstrVal);
break;
case PROP_MAXRANGE:
pvProp->vt = VT_I4;
pvProp->lVal = _lMaxRange;
break;
case PROP_MINRANGE:
pvProp->vt = VT_I4;
pvProp->lVal = _lMinRange;
break;
case PROP_MULTIVALUED:
pvProp->vt = VT_BOOL;
pvProp->boolVal = _fMultiValued? VARIANT_TRUE : VARIANT_FALSE;
break;
case PROP_PROPNAME:
pvProp->vt = VT_BSTR;
hr = ADsAllocString( _pszPropName, &pvProp->bstrVal);
break;
case PROP_METAID:
if (_lMetaId == 0) {
hr = E_ADS_PROPERTY_NOT_SET;
}
else {
pvProp->vt = VT_I4;
pvProp->lVal = _lMetaId;
}
break;
case PROP_USERTYPE:
pvProp->vt = VT_I4;
pvProp->lVal = _lUserType;
break;
case PROP_ALLATTRIBUTES:
pvProp->vt = VT_I4;
pvProp->lVal = _lAllAttributes;
break;
case PROP_INHERIT:
pvProp->vt = VT_BOOL;
pvProp->boolVal = _lAllAttributes & METADATA_INHERIT ?
VARIANT_TRUE : VARIANT_FALSE;
break;
case PROP_SECURE:
pvProp->vt = VT_BOOL;
pvProp->boolVal = _lAllAttributes & METADATA_SECURE ?
VARIANT_TRUE : VARIANT_FALSE;
break;
case PROP_REFERENCE:
pvProp->vt = VT_BOOL;
pvProp->boolVal = _lAllAttributes & METADATA_REFERENCE ?
VARIANT_TRUE : VARIANT_FALSE;
break;
case PROP_VOLATILE:
pvProp->vt = VT_BOOL;
pvProp->boolVal = _lAllAttributes & METADATA_VOLATILE ?
VARIANT_TRUE : VARIANT_FALSE;
break;
case PROP_INSERTPATH:
pvProp->vt = VT_BOOL;
pvProp->boolVal = _lAllAttributes & METADATA_INSERT_PATH ?
VARIANT_TRUE : VARIANT_FALSE;
break;
case PROP_DEFAULT:
VariantCopy(pvProp, &_vDefault);
break;
default:
hr = E_ADS_PROPERTY_NOT_SUPPORTED;
}
error:
RRETURN(hr);
}
HRESULT
CIISProperty::Put(
THIS_ BSTR bstrName,
VARIANT vProp
)
{
HRESULT hr = S_OK;
DWORD dwSyntaxId = 0;
DWORD dwID;
VARIANT vVar;
//
// check if property is a supported property
//
hr = ValidatePropertyObjProps(bstrName, &dwSyntaxId, &dwID);
BAIL_ON_FAILURE(hr);
switch(dwID) {
case PROP_SYNTAX:
if (_bExistProp) {
hr = E_ADS_SCHEMA_VIOLATION;
BAIL_ON_FAILURE(hr);
}
hr = ValidateSyntaxName(vProp.bstrVal, &dwSyntaxId);
BAIL_ON_FAILURE(hr);
hr = ADsReAllocString( &_bstrSyntax,
vProp.bstrVal ? vProp.bstrVal: TEXT("") );
BAIL_ON_FAILURE(hr);
_dwSyntaxId = dwSyntaxId;
if (_dwSyntaxId == IIS_SYNTAX_ID_MIMEMAP ||
_dwSyntaxId == IIS_SYNTAX_ID_MULTISZ) {
_fMultiValued = VARIANT_TRUE;
}
break;
case PROP_MAXRANGE:
hr = CheckVariantDataType(&vProp, VT_I4);
BAIL_ON_FAILURE(hr);
_lMaxRange = vProp.lVal;
break;
case PROP_MINRANGE:
hr = CheckVariantDataType(&vProp, VT_I4);
BAIL_ON_FAILURE(hr);
_lMinRange = vProp.lVal;
break;
case PROP_USERTYPE:
hr = CheckVariantDataType(&vProp, VT_I4);
BAIL_ON_FAILURE(hr);
_lUserType = vProp.lVal;
break;
case PROP_INHERIT:
hr = CheckVariantDataType(&vProp, VT_BOOL);
BAIL_ON_FAILURE(hr);
if (vProp.boolVal == VARIANT_TRUE) {
_lAllAttributes |= METADATA_INHERIT;
}
else {
_lAllAttributes &= ~METADATA_INHERIT;
}
break;
case PROP_PARTIALPATH:
hr = CheckVariantDataType(&vProp, VT_BOOL);
BAIL_ON_FAILURE(hr);
if (vProp.boolVal == VARIANT_TRUE) {
_lAllAttributes |= METADATA_PARTIAL_PATH;
}
else {
_lAllAttributes &= ~METADATA_PARTIAL_PATH;
}
break;
case PROP_SECURE:
hr = CheckVariantDataType(&vProp, VT_BOOL);
BAIL_ON_FAILURE(hr);
if (vProp.boolVal == VARIANT_TRUE) {
_lAllAttributes |= METADATA_SECURE;
}
else {
_lAllAttributes &= ~METADATA_SECURE;
}
break;
case PROP_REFERENCE:
hr = CheckVariantDataType(&vProp, VT_BOOL);
BAIL_ON_FAILURE(hr);
if (vProp.boolVal == VARIANT_TRUE) {
_lAllAttributes |= METADATA_REFERENCE;
}
else {
_lAllAttributes &= ~METADATA_REFERENCE;
}
break;
case PROP_VOLATILE:
hr = CheckVariantDataType(&vProp, VT_BOOL);
BAIL_ON_FAILURE(hr);
if (vProp.boolVal == VARIANT_TRUE) {
_lAllAttributes |= METADATA_VOLATILE;
}
else {
_lAllAttributes &= ~METADATA_VOLATILE;
}
break;
case PROP_ISINHERIT:
hr = CheckVariantDataType(&vProp, VT_BOOL);
BAIL_ON_FAILURE(hr);
if (vProp.boolVal == VARIANT_TRUE) {
_lAllAttributes |= METADATA_ISINHERITED;
}
else {
_lAllAttributes &= ~METADATA_ISINHERITED;
}
break;
case PROP_INSERTPATH:
hr = CheckVariantDataType(&vProp, VT_BOOL);
BAIL_ON_FAILURE(hr);
if (vProp.boolVal == VARIANT_TRUE) {
_lAllAttributes |= METADATA_INSERT_PATH;
}
else {
_lAllAttributes &= ~METADATA_INSERT_PATH;
}
break;
case PROP_DEFAULT:
VariantInit(&vVar);
VariantCopyInd(&vVar, &vProp);
VariantClear( &_vDefault );
_vDefault = vVar;
break;
case PROP_METAID:
hr = CheckVariantDataType(&vProp, VT_I4);
BAIL_ON_FAILURE(hr);
hr = put_MetaId( vProp.lVal );
break;
default:
hr = E_ADS_PROPERTY_NOT_SUPPORTED;
}
error:
RRETURN(hr);
}
STDMETHODIMP
CIISProperty::GetEx(
THIS_ BSTR bstrName,
VARIANT FAR* pvProp
)
{
HRESULT hr = S_OK;
//
// Get and GetEx are the same for property schema object
//
hr = Get(bstrName, pvProp);
RRETURN(hr);
}
STDMETHODIMP
CIISProperty::PutEx(
THIS_ long lnControlCode,
BSTR bstrName,
VARIANT vProp
)
{
RRETURN(E_NOTIMPL);
}
HRESULT
CIISProperty::ConvertDefaultValue(
PVARIANT pVar,
PROPERTYINFO *pPropInfo
)
{
HRESULT hr = S_OK;
LPBYTE *pBuffer;
if (pVar->vt != VT_EMPTY) {
if (pPropInfo->dwSyntaxId == IIS_SYNTAX_ID_DWORD ||
pPropInfo->dwSyntaxId == IIS_SYNTAX_ID_IPSECLIST ||
pPropInfo->dwSyntaxId == IIS_SYNTAX_ID_NTACL ||
pPropInfo->dwSyntaxId == IIS_SYNTAX_ID_BINARY ) {
pPropInfo->dwDefault = (DWORD)pVar->lVal;
}
else if (pPropInfo->dwSyntaxId == IIS_SYNTAX_ID_BOOL ||
pPropInfo->dwSyntaxId == IIS_SYNTAX_ID_BOOL_BITMASK) {
pPropInfo->dwDefault = pVar->boolVal ? 1 : 0;
}
else if (pPropInfo->dwSyntaxId == IIS_SYNTAX_ID_MULTISZ ||
pPropInfo->dwSyntaxId == IIS_SYNTAX_ID_MIMEMAP ) {
hr = MakeMultiStringFromVariantArray(pVar,
(LPBYTE*)&pBuffer);
BAIL_ON_FAILURE(hr);
pPropInfo->szDefault = (LPWSTR) pBuffer;
}
else {
if (pVar->vt == VT_BSTR && pVar->bstrVal && *(pVar->bstrVal)) {
pPropInfo->szDefault = AllocADsStr(pVar->bstrVal);
if (!pPropInfo->szDefault) {
hr = E_OUTOFMEMORY;
BAIL_ON_FAILURE(hr);
}
}
}
}
error:
RRETURN(hr);
}
HRESULT
CIISProperty::ValidateSyntaxName(
LPWSTR pszName,
PDWORD pdwSyntax
)
{
HRESULT hr = S_OK;
DWORD i;
//
// Look for the given syntax name
//
for ( i = 0; i < g_cIISSyntax; i++ )
{
if ( _wcsicmp( g_aIISSyntax[i].bstrName, pszName ) == 0 ) {
*pdwSyntax = g_aIISSyntax[i].dwIISSyntaxId;
RRETURN(S_OK);
}
}
RRETURN(E_ADS_BAD_PARAMETER);
}
/* IADsProperty methods */
STDMETHODIMP
CIISProperty::get_OID( THIS_ BSTR FAR *pbstrOID )
{
RRETURN(E_NOTIMPL);
}
STDMETHODIMP
CIISProperty::put_OID( THIS_ BSTR bstrOID )
{
RRETURN(E_NOTIMPL);
}
STDMETHODIMP
CIISProperty::get_Syntax( THIS_ BSTR FAR *pbstrSyntax )
{
if ( !pbstrSyntax )
RRETURN(E_ADS_BAD_PARAMETER);
RRETURN( ADsAllocString( _bstrSyntax, pbstrSyntax ));
}
STDMETHODIMP
CIISProperty::put_Syntax( THIS_ BSTR bstrSyntax )
{
HRESULT hr_check = _pSchema->ValidatePropertyName(_pszPropName);
if (SUCCEEDED(hr_check)) {
RRETURN(E_FAIL);
}
HRESULT hr;
DWORD dwSyntaxId;
if (_bExistProp) {
RRETURN(E_ADS_SCHEMA_VIOLATION);
}
hr = ValidateSyntaxName(bstrSyntax, &dwSyntaxId);
BAIL_ON_FAILURE(hr);
hr = ADsReAllocString( &_bstrSyntax, bstrSyntax);
BAIL_ON_FAILURE(hr);
_dwSyntaxId = dwSyntaxId;
if (_dwSyntaxId == IIS_SYNTAX_ID_MIMEMAP ||
_dwSyntaxId == IIS_SYNTAX_ID_MULTISZ) {
_fMultiValued = VARIANT_TRUE;
}
error:
RRETURN(hr);
}
STDMETHODIMP
CIISProperty::get_MaxRange( THIS_ long FAR *plMaxRange )
{
if ( !plMaxRange )
RRETURN(E_ADS_BAD_PARAMETER);
*plMaxRange = _lMaxRange;
RRETURN(S_OK);
}
STDMETHODIMP
CIISProperty::put_MaxRange( THIS_ long lMaxRange )
{
HRESULT hr_check = _pSchema->ValidatePropertyName(_pszPropName);
if (SUCCEEDED(hr_check)) {
RRETURN(E_FAIL);
}
_lMaxRange = lMaxRange;
RRETURN(S_OK);
}
STDMETHODIMP
CIISProperty::get_MinRange( THIS_ long FAR *plMinRange )
{
if ( !plMinRange )
RRETURN(E_ADS_BAD_PARAMETER);
*plMinRange = _lMinRange;
RRETURN(S_OK);
}
STDMETHODIMP
CIISProperty::put_MinRange( THIS_ long lMinRange )
{
HRESULT hr_check = _pSchema->ValidatePropertyName(_pszPropName);
if (SUCCEEDED(hr_check)) {
RRETURN(E_FAIL);
}
_lMinRange = lMinRange;
RRETURN(S_OK);
}
STDMETHODIMP
CIISProperty::get_MultiValued( THIS_ VARIANT_BOOL FAR *pfMultiValued )
{
if ( !pfMultiValued )
RRETURN(E_ADS_BAD_PARAMETER);
*pfMultiValued = _fMultiValued;
RRETURN(S_OK);
}
STDMETHODIMP
CIISProperty::put_MultiValued( THIS_ VARIANT_BOOL fMultiValued )
{
RRETURN(E_NOTIMPL);
}
STDMETHODIMP
CIISProperty::Qualifiers(THIS_ IADsCollection FAR* FAR* ppQualifiers)
{
RRETURN(E_NOTIMPL);
}
HRESULT
CIISProperty::AllocatePropertyObject(CIISProperty FAR * FAR * ppProperty)
{
CIISProperty FAR *pProperty = NULL;
CPropertyCache FAR * pPropertyCache = NULL;
CAggregatorDispMgr FAR *pDispMgr = NULL;
HRESULT hr = S_OK;
pProperty = new CIISProperty();
if ( pProperty == NULL )
hr = E_OUTOFMEMORY;
BAIL_ON_FAILURE(hr);
pDispMgr = new CAggregatorDispMgr;
if ( pDispMgr == NULL )
hr = E_OUTOFMEMORY;
BAIL_ON_FAILURE(hr);
hr = pDispMgr->LoadTypeInfoEntry(
LIBID_ADs,
IID_IADs,
(IADs *) pProperty,
DISPID_REGULAR );
BAIL_ON_FAILURE(hr);
hr = pDispMgr->LoadTypeInfoEntry(
LIBID_ADs,
IID_IADsProperty,
(IADsProperty *) pProperty,
DISPID_REGULAR );
BAIL_ON_FAILURE(hr);
hr = pDispMgr->LoadTypeInfoEntry(
LIBID_IISOle,
IID_IISPropertyAttribute,
(IISPropertyAttribute *)pProperty,
DISPID_REGULAR
);
BAIL_ON_FAILURE(hr);
pProperty->_pDispMgr = pDispMgr;
*ppProperty = pProperty;
RRETURN(hr);
error:
delete pDispMgr;
delete pProperty;
RRETURN(hr);
}
STDMETHODIMP
CIISProperty::get_PropName(THIS_ BSTR FAR * retval)
{
HRESULT hr = S_OK;
hr = ADsAllocString((LPWSTR)_pszPropName, retval);
RRETURN(hr);
}
STDMETHODIMP
CIISProperty::get_MetaId(THIS_ LONG FAR * retval)
{
HRESULT hr = S_OK;
if (_lMetaId == 0) {
hr = E_ADS_PROPERTY_NOT_SET;
}
else {
*retval = _lMetaId;
}
RRETURN(hr);
}
STDMETHODIMP
CIISProperty::put_MetaId(THIS_ LONG lMetaId)
{
if (GetObjectState() != ADS_OBJECT_UNBOUND)
{
// Only valid for unsaved objects
RRETURN( E_ADS_OBJECT_EXISTS );
}
if( lMetaId < 0 )
{
// Never a valid metabase id
RRETURN( E_ADS_BAD_PARAMETER );
}
if( !IsMetaIdAvailable( (DWORD)lMetaId ) )
{
// This id is already in use
RRETURN( E_ADS_SCHEMA_VIOLATION );
}
_lMetaId = (DWORD)lMetaId;
RRETURN(S_OK);
}
STDMETHODIMP
CIISProperty::get_UserType(THIS_ LONG FAR * retval)
{
*retval = _lUserType;
RRETURN(S_OK);
}
STDMETHODIMP
CIISProperty::put_UserType(THIS_ LONG lUserType)
{
HRESULT hr_check = _pSchema->ValidatePropertyName(_pszPropName);
if (SUCCEEDED(hr_check)) {
RRETURN(E_FAIL);
}
_lUserType = (DWORD)lUserType;
RRETURN(S_OK);
}
STDMETHODIMP
CIISProperty::get_AllAttributes(THIS_ LONG FAR * retval)
{
*retval = _lAllAttributes;
RRETURN(S_OK);
}
STDMETHODIMP
CIISProperty::get_Inherit(THIS_ VARIANT_BOOL FAR * retval)
{
*retval = _lAllAttributes & METADATA_INHERIT ?
VARIANT_TRUE : VARIANT_FALSE;
RRETURN(S_OK);
}
STDMETHODIMP
CIISProperty::put_Inherit(THIS_ VARIANT_BOOL bInherit)
{
HRESULT hr_check = _pSchema->ValidatePropertyName(_pszPropName);
if (SUCCEEDED(hr_check)) {
RRETURN(E_FAIL);
}
if (bInherit == VARIANT_TRUE) {
_lAllAttributes |= METADATA_INHERIT;
}
else {
_lAllAttributes &= ~METADATA_INHERIT;
}
RRETURN(S_OK);
}
STDMETHODIMP
CIISProperty::get_PartialPath(THIS_ VARIANT_BOOL FAR * retval)
{
RRETURN(E_NOTIMPL);
}
STDMETHODIMP
CIISProperty::put_PartialPath(THIS_ VARIANT_BOOL bPartialPath)
{
RRETURN(E_NOTIMPL);
}
STDMETHODIMP
CIISProperty::get_Reference(THIS_ VARIANT_BOOL FAR * retval)
{
*retval = _lAllAttributes & METADATA_REFERENCE ?
VARIANT_TRUE : VARIANT_FALSE;
RRETURN(S_OK);
}
STDMETHODIMP
CIISProperty::put_Reference(THIS_ VARIANT_BOOL bReference)
{
HRESULT hr_check = _pSchema->ValidatePropertyName(_pszPropName);
if (SUCCEEDED(hr_check)) {
RRETURN(E_FAIL);
}
if (bReference == VARIANT_TRUE) {
_lAllAttributes |= METADATA_REFERENCE;
}
else {
_lAllAttributes &= ~METADATA_REFERENCE;
}
RRETURN(S_OK);
}
STDMETHODIMP
CIISProperty::get_Secure(THIS_ VARIANT_BOOL FAR * retval)
{
*retval = _lAllAttributes & METADATA_SECURE ?
VARIANT_TRUE : VARIANT_FALSE;
RRETURN(S_OK);
}
STDMETHODIMP
CIISProperty::put_Secure(THIS_ VARIANT_BOOL bSecure)
{
HRESULT hr_check = _pSchema->ValidatePropertyName(_pszPropName);
if (SUCCEEDED(hr_check)) {
RRETURN(E_FAIL);
}
if (bSecure == VARIANT_TRUE) {
_lAllAttributes |= METADATA_SECURE;
}
else {
_lAllAttributes &= ~METADATA_SECURE;
}
RRETURN(S_OK);
}
STDMETHODIMP
CIISProperty::get_Volatile(THIS_ VARIANT_BOOL FAR * retval)
{
*retval = _lAllAttributes & METADATA_VOLATILE ?
VARIANT_TRUE : VARIANT_FALSE;
RRETURN(S_OK);
}
STDMETHODIMP
CIISProperty::put_Volatile(THIS_ VARIANT_BOOL bVolatile)
{
HRESULT hr_check = _pSchema->ValidatePropertyName(_pszPropName);
if (SUCCEEDED(hr_check)) {
RRETURN(E_FAIL);
}
if (bVolatile == VARIANT_TRUE) {
_lAllAttributes |= METADATA_VOLATILE;
}
else {
_lAllAttributes &= ~METADATA_VOLATILE;
}
RRETURN(S_OK);
}
STDMETHODIMP
CIISProperty::get_Isinherit(THIS_ VARIANT_BOOL FAR * retval)
{
RRETURN(E_NOTIMPL);
}
STDMETHODIMP
CIISProperty::put_Isinherit(THIS_ VARIANT_BOOL bIsinherit)
{
RRETURN(E_NOTIMPL);
}
STDMETHODIMP
CIISProperty::get_InsertPath(THIS_ VARIANT_BOOL FAR * retval)
{
*retval = _lAllAttributes & METADATA_INSERT_PATH ?
VARIANT_TRUE : VARIANT_FALSE;
RRETURN(S_OK);
}
STDMETHODIMP
CIISProperty::put_InsertPath(THIS_ VARIANT_BOOL bInsertPath)
{
HRESULT hr_check = _pSchema->ValidatePropertyName(_pszPropName);
if (SUCCEEDED(hr_check)) {
RRETURN(E_FAIL);
}
if (bInsertPath == VARIANT_TRUE) {
_lAllAttributes |= METADATA_INSERT_PATH;
}
else {
_lAllAttributes &= ~METADATA_INSERT_PATH;
}
RRETURN(S_OK);
}
STDMETHODIMP
CIISProperty::get_Default(THIS_ VARIANT FAR * retval)
{
VariantInit(retval);
RRETURN(VariantCopy(retval, &_vDefault));
}
STDMETHODIMP
CIISProperty::put_Default(THIS_ VARIANT vVarDefault)
{
HRESULT hr_check = _pSchema->ValidatePropertyName(_pszPropName);
if (SUCCEEDED(hr_check)) {
RRETURN(E_FAIL);
}
VariantClear(&_vDefault);
RRETURN(VariantCopy(&_vDefault, &vVarDefault));
}
HRESULT
CIISProperty::SetMetaID()
{
HRESULT hr = S_OK;
DWORD dwMetaId;
//
// get metaid
//
if (_lMetaId == 0) {
hr = _pSchema->LookupMetaID(_pszPropName, &dwMetaId);
//
// generate a meta id for this property
//
if (FAILED(hr)) {
hr = GenerateNewMetaID(_pszServerName, _pAdminBase, &dwMetaId);
BAIL_ON_FAILURE(hr);
//
// since we don't support bit mask property for ext. schema,
// propid == metaid
//
_dwPropID = dwMetaId;
}
else {
hr = _pSchema->LookupPropID(_pszPropName, &_dwPropID);
ASSERT(hr);
}
//
// assign new metaid to property
//
_lMetaId = (LONG)dwMetaId;
}
error:
RRETURN(hr);
}
BOOL
CIISProperty::IsMetaIdAvailable(
DWORD MetaId
)
/*++
Routine Description:
Determine if the ID is valid to set on a new property.
The determinination is based on whether the id is not
currently in use.
NOTE - We will not respect ranges of IDs reserved for
the base object. Unless that value is already defined
(per vanvan)
Arguments:
MetaId - The ID to validate
Return Value:
TRUE if the specified id is valid to set, FALSE otherwise
--*/
{
BOOL fRet = FALSE;
HRESULT hr = NOERROR;
METADATA_HANDLE hObjHandle = NULL;
// Is the property specified by MetaId defined in the schema
hr = OpenAdminBaseKey(
_pszServerName,
SCHEMA_PROP_METABASE_PATH,
METADATA_PERMISSION_READ,
&_pAdminBase,
&hObjHandle
);
if( SUCCEEDED(hr) )
{
METADATA_RECORD mdr;
WCHAR wcsPropertyName[MAX_PATH + 1];
DWORD cb;
MD_SET_DATA_RECORD( &mdr,
MetaId,
METADATA_NO_ATTRIBUTES,
IIS_MD_UT_SERVER,
STRING_METADATA,
sizeof(wcsPropertyName),
(unsigned char *)wcsPropertyName
);
hr = _pAdminBase->GetData( hObjHandle, L"Names", &mdr, &cb );
if( MD_ERROR_DATA_NOT_FOUND == hr )
{
fRet = TRUE;
}
CloseAdminBaseKey(_pAdminBase, hObjHandle);
}
return fRet;
}
/******************************************************************/
/* Class CIISSyntax
/******************************************************************/
DEFINE_IDispatch_Implementation(CIISSyntax)
DEFINE_IADs_Implementation(CIISSyntax)
DEFINE_IADs_PutGetUnImplementation(CIISSyntax)
CIISSyntax::CIISSyntax() : _pSchema(NULL),
_pDispMgr(NULL)
{
ENLIST_TRACKING(CIISSyntax);
}
CIISSyntax::~CIISSyntax()
{
delete _pDispMgr;
}
HRESULT
CIISSyntax::CreateSyntax(
BSTR bstrParent,
SYNTAXINFO *pSyntaxInfo,
DWORD dwObjectState,
REFIID riid,
void **ppvObj
)
{
CIISSyntax FAR *pSyntax = NULL;
HRESULT hr = S_OK;
hr = AllocateSyntaxObject( &pSyntax );
BAIL_ON_FAILURE(hr);
hr = pSyntax->InitializeCoreObject(
bstrParent,
pSyntaxInfo->bstrName,
SYNTAX_CLASS_NAME,
NO_SCHEMA,
CLSID_IISSyntax,
dwObjectState );
BAIL_ON_FAILURE(hr);
pSyntax->_lOleAutoDataType = pSyntaxInfo->lOleAutoDataType;
hr = pSyntax->QueryInterface( riid, ppvObj );
BAIL_ON_FAILURE(hr);
pSyntax->Release();
RRETURN(hr);
error:
delete pSyntax;
RRETURN(hr);
}
STDMETHODIMP
CIISSyntax::QueryInterface(REFIID iid, LPVOID FAR* ppv)
{
if (IsEqualIID(iid, IID_IUnknown))
{
*ppv = (IADs FAR *) this;
}
else if (IsEqualIID(iid, IID_IDispatch))
{
*ppv = (IADs FAR *) this;
}
else if (IsEqualIID(iid, IID_IADs))
{
*ppv = (IADs FAR *) this;
}
else if (IsEqualIID(iid, IID_IADsSyntax))
{
*ppv = (IADsSyntax FAR *) this;
}
else
{
*ppv = NULL;
return E_NOINTERFACE;
}
AddRef();
return NOERROR;
}
/* IADs methods */
STDMETHODIMP
CIISSyntax::SetInfo(THIS)
{
RRETURN(E_NOTIMPL);
}
STDMETHODIMP
CIISSyntax::GetInfo(THIS)
{
RRETURN(S_OK);
}
HRESULT
CIISSyntax::AllocateSyntaxObject(CIISSyntax FAR * FAR * ppSyntax)
{
CIISSyntax FAR *pSyntax = NULL;
CAggregatorDispMgr FAR *pDispMgr = NULL;
HRESULT hr = S_OK;
pSyntax = new CIISSyntax();
if ( pSyntax == NULL )
hr = E_OUTOFMEMORY;
BAIL_ON_FAILURE(hr);
pDispMgr = new CAggregatorDispMgr;
if ( pDispMgr == NULL )
hr = E_OUTOFMEMORY;
BAIL_ON_FAILURE(hr);
hr = pDispMgr->LoadTypeInfoEntry(
LIBID_ADs,
IID_IADsSyntax,
(IADsSyntax *) pSyntax,
DISPID_REGULAR );
BAIL_ON_FAILURE(hr);
pSyntax->_pDispMgr = pDispMgr;
*ppSyntax = pSyntax;
RRETURN(hr);
error:
delete pDispMgr;
delete pSyntax;
RRETURN(hr);
}
STDMETHODIMP
CIISSyntax::get_OleAutoDataType( THIS_ long FAR *plOleAutoDataType )
{
if ( !plOleAutoDataType )
RRETURN(E_ADS_BAD_PARAMETER);
*plOleAutoDataType = _lOleAutoDataType;
RRETURN(S_OK);
}
STDMETHODIMP
CIISSyntax::put_OleAutoDataType( THIS_ long lOleAutoDataType )
{
RRETURN(E_ADS_PROPERTY_NOT_SUPPORTED);
}
/******************************************************************/
/* Misc Helpers
/******************************************************************/
HRESULT
MakeVariantFromStringList(
BSTR bstrList,
VARIANT *pvVariant
)
{
HRESULT hr = S_OK;
SAFEARRAY *aList = NULL;
SAFEARRAYBOUND aBound;
BSTR pszTempList = NULL;
if ( bstrList != NULL )
{
// If bstrList is not null, then there we consider there
// to be one element
long nCount = 1;
long i = 0;
TCHAR c;
BSTR pszSrc;
hr = ADsAllocString( bstrList, &pszTempList );
BAIL_ON_FAILURE(hr);
while ( c = pszTempList[i] )
{
if ( c == TEXT(','))
{
pszTempList[i] = 0;
nCount++;
}
i++;
}
aBound.lLbound = 0;
aBound.cElements = nCount;
aList = SafeArrayCreate( VT_VARIANT, 1, &aBound );
if ( aList == NULL )
{
hr = E_OUTOFMEMORY;
BAIL_ON_FAILURE(hr);
}
pszSrc = pszTempList;
for ( i = 0; i < nCount; i++ )
{
VARIANT v;
VariantInit(&v);
V_VT(&v) = VT_BSTR;
hr = ADsAllocString( pszSrc, &(V_BSTR(&v)));
BAIL_ON_FAILURE(hr);
hr = SafeArrayPutElement( aList,
&i,
&v );
VariantClear(&v);
BAIL_ON_FAILURE(hr);
pszSrc += _tcslen( pszSrc ) + 1;
}
VariantInit( pvVariant );
V_VT(pvVariant) = VT_ARRAY | VT_VARIANT;
V_ARRAY(pvVariant) = aList;
ADsFreeString( pszTempList );
pszTempList = NULL;
}
else
{
aBound.lLbound = 0;
aBound.cElements = 0;
aList = SafeArrayCreate( VT_VARIANT, 1, &aBound );
if ( aList == NULL )
{
hr = E_OUTOFMEMORY;
BAIL_ON_FAILURE(hr);
}
VariantInit( pvVariant );
V_VT(pvVariant) = VT_ARRAY | VT_VARIANT;
V_ARRAY(pvVariant) = aList;
}
RRETURN(S_OK);
error:
if ( pszTempList )
ADsFreeString( pszTempList );
if ( aList )
SafeArrayDestroy( aList );
RRETURN(hr);
}
HRESULT
ValidateClassObjProps(
LPWSTR pszName,
PDWORD pdwSyntax,
PDWORD pdwID
)
{
DWORD i;
//
// Look for the given syntax name
//
for ( i = 0; i < g_cClassObjProps; i++ )
{
if ( _wcsicmp( g_pClassObjProps[i].szObjectName, pszName) == 0 ) {
*pdwSyntax = g_pClassObjProps[i].dwSyntaxId;
*pdwID = g_pClassObjProps[i].dwID;
RRETURN(S_OK);
}
}
RRETURN(E_ADS_BAD_PARAMETER);
}
HRESULT
ValidatePropertyObjProps(
LPWSTR pszName,
PDWORD pdwSyntax,
PDWORD pdwID
)
{
DWORD i;
//
// Look for the given syntax name
//
for ( i = 0; i < g_cPropertyObjProps; i++ )
{
if ( _wcsicmp( g_pPropertyObjProps[i].szObjectName, pszName) == 0 ) {
*pdwSyntax = g_pPropertyObjProps[i].dwSyntaxId;
*pdwID = g_pPropertyObjProps[i].dwID;
RRETURN(S_OK);
}
}
RRETURN(E_ADS_BAD_PARAMETER);
}
HRESULT
IISMarshallClassProperties(
CLASSINFO *pClassInfo,
PMETADATA_RECORD * ppMetaDataRecords,
PDWORD pdwMDNumDataEntries
)
{
HRESULT hr = S_OK;
PMETADATA_RECORD pMetaDataArray = NULL;
static BOOL bTemp = FALSE;
//
// set to 4 because we're supporting 4 properties only
//
*pdwMDNumDataEntries = 4;
pMetaDataArray = (PMETADATA_RECORD) AllocADsMem(
*pdwMDNumDataEntries * sizeof(METADATA_RECORD));
if (!pMetaDataArray ) {
hr = E_OUTOFMEMORY;
BAIL_ON_FAILURE(hr);
}
*ppMetaDataRecords = pMetaDataArray;
//
// setting Containment and Container property for classes
//
pMetaDataArray->dwMDIdentifier = MD_SCHEMA_CLASS_CONTAINER;
pMetaDataArray->dwMDAttributes = METADATA_NO_ATTRIBUTES;
pMetaDataArray->dwMDUserType = IIS_MD_UT_SERVER;
pMetaDataArray->dwMDDataType = DWORD_METADATA;
pMetaDataArray->dwMDDataLen = sizeof(DWORD);
if (pClassInfo) {
pMetaDataArray->pbMDData = (unsigned char*)&(pClassInfo->fContainer);
}
else {
pMetaDataArray->pbMDData = (BYTE*)&bTemp;
}
pMetaDataArray++;
pMetaDataArray->dwMDIdentifier = MD_SCHEMA_CLASS_CONTAINMENT;
pMetaDataArray->dwMDAttributes = METADATA_NO_ATTRIBUTES;
pMetaDataArray->dwMDUserType = IIS_MD_UT_SERVER;
pMetaDataArray->dwMDDataType = STRING_METADATA;
if (pClassInfo && pClassInfo->bstrContainment) {
pMetaDataArray->dwMDDataLen = (wcslen((LPWSTR)pClassInfo->bstrContainment)+ 1)*2;
pMetaDataArray->pbMDData = (unsigned char *)pClassInfo->bstrContainment;
}
else {
pMetaDataArray->dwMDDataLen = 0;
pMetaDataArray->pbMDData = NULL;
}
pMetaDataArray++;
//
// setting Optional and Mandatory Properties
//
pMetaDataArray->dwMDIdentifier = MD_SCHEMA_CLASS_MAND_PROPERTIES;
pMetaDataArray->dwMDAttributes = METADATA_NO_ATTRIBUTES;
pMetaDataArray->dwMDUserType = IIS_MD_UT_SERVER;
pMetaDataArray->dwMDDataType = STRING_METADATA;
if (pClassInfo && pClassInfo->bstrMandatoryProperties) {
pMetaDataArray->dwMDDataLen = (wcslen((LPWSTR)pClassInfo->bstrMandatoryProperties)+1)*2;
pMetaDataArray->pbMDData = (unsigned char *)pClassInfo->bstrMandatoryProperties;
}
else {
pMetaDataArray->dwMDDataLen = 0;
pMetaDataArray->pbMDData = NULL;
}
pMetaDataArray++;
pMetaDataArray->dwMDIdentifier = MD_SCHEMA_CLASS_OPT_PROPERTIES;
pMetaDataArray->dwMDAttributes = METADATA_NO_ATTRIBUTES;
pMetaDataArray->dwMDUserType = IIS_MD_UT_SERVER;
pMetaDataArray->dwMDDataType = STRING_METADATA;
if (pClassInfo && pClassInfo->bstrOptionalProperties) {
pMetaDataArray->dwMDDataLen = (wcslen((LPWSTR)pClassInfo->bstrOptionalProperties)+1)*2;
pMetaDataArray->pbMDData = (unsigned char *)pClassInfo->bstrOptionalProperties;
}
else {
pMetaDataArray->dwMDDataLen = 0;
pMetaDataArray->pbMDData = NULL;
}
error:
RRETURN(hr);
}
HRESULT
GenerateNewMetaID(
LPWSTR pszServerName,
IMSAdminBase *pAdminBase,
PDWORD pdwMetaID
)
{
HRESULT hr = S_OK;
DWORD dwMetaId = 0;
METADATA_HANDLE hObjHandle = NULL;
DWORD dwBufferSize = sizeof(DWORD);
METADATA_RECORD mdrMDData;
LPBYTE pBuffer = (LPBYTE)&dwMetaId;
hr = OpenAdminBaseKey(
pszServerName,
IIS_MD_ADSI_SCHEMA_PATH_W,
METADATA_PERMISSION_READ | METADATA_PERMISSION_WRITE,
&pAdminBase,
&hObjHandle
);
BAIL_ON_FAILURE(hr);
MD_SET_DATA_RECORD(&mdrMDData,
MD_SCHEMA_METAID,
METADATA_NO_ATTRIBUTES,
IIS_MD_UT_SERVER,
DWORD_METADATA,
dwBufferSize,
pBuffer);
hr = pAdminBase->GetData(
hObjHandle,
L"",
&mdrMDData,
&dwBufferSize
);
BAIL_ON_FAILURE(hr);
*pdwMetaID = dwMetaId;
//
// increment metaid by 1 for next property
//
dwMetaId++;
hr = pAdminBase->SetData(
hObjHandle,
L"",
&mdrMDData
);
BAIL_ON_FAILURE(hr);
error:
if (hObjHandle) {
CloseAdminBaseKey(pAdminBase, hObjHandle);
}
RRETURN(hr);
}
HRESULT
CheckDuplicateNames(
LPWSTR pszNames
)
{
WCHAR szName[MAX_PATH];
WCHAR szName2[MAX_PATH];
LPWSTR ObjectList = (LPWSTR)pszNames;
LPWSTR CheckList = (LPWSTR)pszNames;
DWORD dwCount = 0;
if (ObjectList == NULL ||
(ObjectList != NULL && *ObjectList == NULL)) {
RRETURN(S_OK);
}
while ((ObjectList = grabProp(szName, ObjectList)) != NULL) {
if (*szName != L'\0') {
CheckList = pszNames;
while ((CheckList = grabProp(szName2, CheckList)) != NULL) {
if (*szName2 != L'\0') {
if (!_wcsicmp(szName, szName2)) {
dwCount++;
}
}
}
if (dwCount > 1) {
RRETURN(E_ADS_BAD_PARAMETER);
}
dwCount = 0;
}
}
RRETURN(S_OK);
}