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

731 lines
16 KiB
C++

//---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1997.
//
// File: cschobj.cxx
//
// Contents: Microsoft ADs IIS Provider Schema Object
//
//
// History: 01-30-98 sophiac Created.
//
//----------------------------------------------------------------------------
#include "iis.hxx"
#pragma hdrstop
// Class CIISSchema
DEFINE_IDispatch_Implementation(CIISSchema)
DEFINE_IADs_Implementation(CIISSchema)
CIISSchema::CIISSchema() :
_pSchema(NULL),
_pDispMgr(NULL),
_pszServerName(NULL),
_pAdminBase(NULL)
{
ENLIST_TRACKING(CIISSchema);
}
HRESULT
CIISSchema::CreateSchema(
LPWSTR pszServerName,
BSTR Parent,
BSTR CommonName,
DWORD dwObjectState,
REFIID riid,
void **ppvObj
)
{
CIISSchema FAR * pSchema = NULL;
HRESULT hr = S_OK;
hr = AllocateSchemaObject(&pSchema);
BAIL_ON_FAILURE(hr);
hr = InitServerInfo(pszServerName,
&pSchema->_pAdminBase,
&pSchema->_pSchema);
BAIL_ON_FAILURE(hr);
pSchema->_pszServerName = AllocADsStr(pszServerName);
if (!pSchema->_pszServerName) {
hr = E_OUTOFMEMORY;
BAIL_ON_FAILURE(hr);
}
hr = pSchema->InitializeCoreObject(
Parent,
CommonName,
SCHEMA_CLASS_NAME,
L"",
CLSID_IISSchema,
dwObjectState
);
BAIL_ON_FAILURE(hr);
hr = pSchema->QueryInterface(riid, ppvObj);
BAIL_ON_FAILURE(hr);
pSchema->Release();
RRETURN(hr);
error:
delete pSchema;
RRETURN(hr);
}
CIISSchema::~CIISSchema( )
{
delete _pDispMgr;
if (_pszServerName) {
FreeADsStr(_pszServerName);
}
}
STDMETHODIMP
CIISSchema::QueryInterface(REFIID iid, LPVOID FAR* ppv)
{
if (IsEqualIID(iid, IID_IUnknown))
{
*ppv = (IADs FAR *) this;
}
else if (IsEqualIID(iid, IID_IADsContainer))
{
*ppv = (IADsContainer 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_IDispatch))
{
*ppv = (IADs FAR *) this;
}
else
{
*ppv = NULL;
return E_NOINTERFACE;
}
AddRef();
return NOERROR;
}
STDMETHODIMP
CIISSchema::SetInfo(THIS)
{
RRETURN(E_NOTIMPL);
}
STDMETHODIMP
CIISSchema::GetInfo(THIS)
{
RRETURN(E_NOTIMPL);
}
/* IADsContainer methods */
STDMETHODIMP
CIISSchema::get_Count(long FAR* retval)
{
HRESULT hr;
DWORD dwEntries;
if ( !retval )
RRETURN(E_ADS_BAD_PARAMETER);
hr = _pSchema->GetTotalEntries(&dwEntries);
if ( SUCCEEDED(hr))
*retval = dwEntries + g_cIISSyntax;
RRETURN(hr);
}
STDMETHODIMP
CIISSchema::get_Filter(THIS_ VARIANT FAR* pVar)
{
RRETURN(E_NOTIMPL);
}
STDMETHODIMP
CIISSchema::put_Filter(THIS_ VARIANT Var)
{
RRETURN(E_NOTIMPL);
}
STDMETHODIMP
CIISSchema::put_Hints(THIS_ VARIANT Var)
{
RRETURN( E_NOTIMPL);
}
STDMETHODIMP
CIISSchema::get_Hints(THIS_ VARIANT FAR* pVar)
{
RRETURN(E_NOTIMPL);
}
STDMETHODIMP
CIISSchema::GetObject(
THIS_ BSTR ClassName,
BSTR RelativeName,
IDispatch * FAR* ppObject
)
{
LPWSTR pszBuffer = NULL;
HRESULT hr = S_OK;
DWORD dwLen;
CCredentials Credentials;
*ppObject = NULL;
if (!RelativeName || !*RelativeName) {
RRETURN(E_ADS_UNKNOWN_OBJECT);
}
dwLen = wcslen(_ADsPath) + wcslen(RelativeName) + wcslen(ClassName) + 4;
pszBuffer = (LPWSTR)AllocADsMem(dwLen*sizeof(WCHAR));
if (!pszBuffer) {
hr = E_OUTOFMEMORY;
BAIL_ON_FAILURE(hr);
}
wcscpy(pszBuffer, _ADsPath);
wcscat(pszBuffer, L"/");
wcscat(pszBuffer, RelativeName);
if (ClassName && *ClassName) {
wcscat(pszBuffer,L",");
wcscat(pszBuffer, ClassName);
}
hr = ::GetObject(
pszBuffer,
Credentials,
(LPVOID *)ppObject
);
BAIL_ON_FAILURE(hr);
error:
if (pszBuffer) {
FreeADsMem(pszBuffer);
}
RRETURN(hr);
}
STDMETHODIMP
CIISSchema::get__NewEnum(
THIS_ IUnknown * FAR* retval
)
{
HRESULT hr;
IUnknown FAR* punkEnum=NULL;
IEnumVARIANT * penum = NULL;
if ( !retval )
RRETURN(E_ADS_BAD_PARAMETER);
*retval = NULL;
hr = CIISSchemaEnum::Create(
(CIISSchemaEnum **)&penum,
_pSchema,
_ADsPath,
_Name
);
BAIL_ON_FAILURE(hr);
hr = penum->QueryInterface(
IID_IUnknown,
(VOID FAR* FAR*)retval
);
BAIL_ON_FAILURE(hr);
if (penum) {
penum->Release();
}
RRETURN(NOERROR);
error:
if (penum) {
delete penum;
}
RRETURN(hr);
}
STDMETHODIMP
CIISSchema::Create(
THIS_ BSTR ClassName,
BSTR RelativeName,
IDispatch * FAR* ppObject
)
{
HRESULT hr = S_OK;
DWORD i = 1;
//
// We can only create "Class","Property" here, "Syntax" is read-only
//
//
// check if property/class already exists
//
if (_pSchema->ValidateClassName(RelativeName) == ERROR_SUCCESS ||
_pSchema->ValidatePropertyName(RelativeName) == ERROR_SUCCESS ) {
hr = E_ADS_OBJECT_EXISTS;
BAIL_ON_FAILURE(hr);
}
//
// validate name -->
// must start w/ a-z, A-Z, or underscore
// must only contain a-z, A-Z, 0-9, or underscore
//
// check first character
if ( // if first char is
(RelativeName[0] < 65 || RelativeName[0] > 90) && // not uppercase letter and
(RelativeName[0] < 97 || RelativeName[0] > 122) && // not lowercase letter and
RelativeName[0] != 95 // not underscore
) // then bail
{
hr = E_ADS_BAD_PARAMETER;
BAIL_ON_FAILURE(hr);
}
while ( // while characters are
(RelativeName[i] >= 65 && RelativeName[i] <= 90) || // uppercase letters or
(RelativeName[i] >= 97 && RelativeName[i] <= 122) || // lowercase letters or
(RelativeName[i] >= 48 && RelativeName[i] <= 57) || // digits or
RelativeName[i] == 95 // underscores
) // then things are okay
i++;
if (RelativeName[i] != L'\0' || i >= METADATA_MAX_NAME_LEN) {
hr = E_ADS_BAD_PARAMETER;
BAIL_ON_FAILURE(hr);
}
if ( ( _wcsicmp( ClassName, CLASS_CLASS_NAME ) == 0 ) )
{
//
// Now, create the class
//
hr = CIISClass::CreateClass(
_ADsPath,
RelativeName,
ADS_OBJECT_UNBOUND,
IID_IUnknown,
(void **) ppObject );
}
else if ( ( _wcsicmp( ClassName, PROPERTY_CLASS_NAME ) == 0 ) )
{
hr = CIISProperty::CreateProperty(
_ADsPath,
RelativeName,
ADS_OBJECT_UNBOUND,
IID_IUnknown,
(void **) ppObject );
}
else
{
hr = E_ADS_BAD_PARAMETER;
}
error:
RRETURN(hr);
}
STDMETHODIMP
CIISSchema::Delete(
THIS_ BSTR bstrClassName,
BSTR bstrRelativeName
)
{
HRESULT hr;
BOOL bClass;
METADATA_HANDLE hObjHandle = NULL;
if ( ( _wcsicmp( bstrClassName, CLASS_CLASS_NAME ) == 0 ) )
{
hr = _pSchema->ValidateClassName(bstrRelativeName);
BAIL_ON_FAILURE(hr);
bClass = TRUE;
//
// remove entry from metabase
//
hr = OpenAdminBaseKey(
_pszServerName,
SCHEMA_CLASS_METABASE_PATH,
METADATA_PERMISSION_WRITE,
&_pAdminBase,
&hObjHandle
);
BAIL_ON_FAILURE(hr);
hr = MetaBaseDeleteObject(
_pAdminBase,
hObjHandle,
(LPWSTR)bstrRelativeName
);
if (hr == MD_ERROR_DATA_NOT_FOUND) {
hr = S_OK;
}
BAIL_ON_FAILURE(hr);
}
else if ( ( _wcsicmp( bstrClassName, PROPERTY_CLASS_NAME ) == 0 ) )
{
DWORD dwMetaId;
hr = _pSchema->ValidatePropertyName(bstrRelativeName);
BAIL_ON_FAILURE(hr);
bClass = FALSE;
//
// Lookup metaid
//
hr = _pSchema->LookupMetaID(bstrRelativeName, &dwMetaId);
BAIL_ON_FAILURE(hr);
//
// remove entry from metabase
//
hr = OpenAdminBaseKey(
_pszServerName,
SCHEMA_PROP_METABASE_PATH,
METADATA_PERMISSION_WRITE,
&_pAdminBase,
&hObjHandle
);
BAIL_ON_FAILURE(hr);
hr = _pAdminBase->DeleteData(
hObjHandle,
(LPWSTR)L"Names",
dwMetaId,
ALL_METADATA
);
if (hr == MD_ERROR_DATA_NOT_FOUND) {
hr = S_OK;
}
BAIL_ON_FAILURE(hr);
hr = _pAdminBase->DeleteData(
hObjHandle,
(LPWSTR)L"Types",
dwMetaId,
ALL_METADATA
);
if (hr == MD_ERROR_DATA_NOT_FOUND) {
hr = S_OK;
}
BAIL_ON_FAILURE(hr);
hr = _pAdminBase->DeleteData(
hObjHandle,
(LPWSTR)L"Defaults",
dwMetaId,
ALL_METADATA
);
if (hr == MD_ERROR_DATA_NOT_FOUND) {
hr = S_OK;
}
BAIL_ON_FAILURE(hr);
}
else
{
hr = E_ADS_BAD_PARAMETER;
BAIL_ON_FAILURE(hr);
}
//
// remove entry from schema cache
//
hr = _pSchema->RemoveEntry(bClass, bstrRelativeName);
error:
if (_pAdminBase && hObjHandle) {
CloseAdminBaseKey(_pAdminBase, hObjHandle);
}
RRETURN(hr);
}
STDMETHODIMP
CIISSchema::CopyHere(
THIS_ BSTR SourceName,
BSTR NewName,
IDispatch * FAR* ppObject
)
{
RRETURN(E_NOTIMPL);
}
STDMETHODIMP
CIISSchema::MoveHere(
THIS_ BSTR SourceName,
BSTR NewName,
IDispatch * FAR* ppObject
)
{
RRETURN(E_NOTIMPL);
}
HRESULT
CIISSchema::AllocateSchemaObject(
CIISSchema ** ppSchema
)
{
CIISSchema FAR * pSchema = NULL;
CAggregatorDispMgr FAR * pDispMgr = NULL;
HRESULT hr = S_OK;
pSchema = new CIISSchema();
if (pSchema == 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 *)pSchema,
DISPID_REGULAR
);
BAIL_ON_FAILURE(hr);
hr = pDispMgr->LoadTypeInfoEntry(
LIBID_ADs,
IID_IADsContainer,
(IADsContainer *)pSchema,
DISPID_NEWENUM
);
BAIL_ON_FAILURE(hr);
hr = pDispMgr->LoadTypeInfoEntry(
LIBID_IISOle,
IID_IISSchemaObject,
(IISSchemaObject *)pSchema,
DISPID_REGULAR
);
BAIL_ON_FAILURE(hr);
pSchema->_pDispMgr = pDispMgr;
*ppSchema = pSchema;
RRETURN(hr);
error:
delete pDispMgr;
delete pSchema;
RRETURN(hr);
}
STDMETHODIMP
CIISSchema::GetInfo(
THIS_ DWORD dwApiLevel,
BOOL fExplicit
)
{
RRETURN(E_NOTIMPL);
}
STDMETHODIMP
CIISSchema::Get(
THIS_ BSTR bstrName,
VARIANT FAR* pvProp
)
{
RRETURN(E_NOTIMPL);
}
STDMETHODIMP
CIISSchema::Put(
THIS_ BSTR bstrName,
VARIANT vProp
)
{
RRETURN(E_NOTIMPL);
}
STDMETHODIMP
CIISSchema::GetEx(
THIS_ BSTR bstrName,
VARIANT FAR* pvProp
)
{
RRETURN(E_NOTIMPL);
}
STDMETHODIMP
CIISSchema::PutEx(
THIS_ long lnControlCode,
BSTR bstrName,
VARIANT vProp
)
{
RRETURN(E_NOTIMPL);
}
STDMETHODIMP
CIISSchema::GetSchemaPropertyAttributes(
THIS_ BSTR bstrName,
IDispatch * FAR* ppObject
)
{
HRESULT hr = S_OK;
DWORD dwMetaId;
PROPERTYINFO *pPropertyInfo = NULL;
DWORD i = 0;
IISPropertyAttribute * pPropAttrib = NULL;
WCHAR wchName[MAX_PATH];
VARIANT vVar;
VariantInit(&vVar);
*ppObject = NULL;
//
// if passed in bstrName is a meta id, then convert it to property name
//
if (wcslen(bstrName) >= MAX_PATH) bstrName[MAX_PATH - 1] = L'\0';
wcscpy((LPWSTR)wchName, bstrName);
while (wchName[i] != L'\0' && wchName[i] >= L'0' &&
wchName[i] <= L'9') {
i++;
}
if (i == wcslen((LPWSTR)wchName)) {
dwMetaId = _wtoi((LPWSTR)wchName);
hr = _pSchema->ConvertID_To_PropName(dwMetaId, (LPWSTR)wchName);
BAIL_ON_FAILURE(hr);
}
else {
//
// check if property is a supported property
//
hr = _pSchema->LookupMetaID(wchName, &dwMetaId);
BAIL_ON_FAILURE(hr);
}
//
// get property attribute value
//
pPropertyInfo = _pSchema->GetPropertyInfo(wchName);
ASSERT(pPropertyInfo != NULL);
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 ) {
vVar.vt = VT_I4;
vVar.lVal = pPropertyInfo->dwDefault;
}
else if (pPropertyInfo->dwSyntaxId == IIS_SYNTAX_ID_BOOL ||
pPropertyInfo->dwSyntaxId == IIS_SYNTAX_ID_BOOL_BITMASK) {
vVar.vt = VT_BOOL;
vVar.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,
&vVar);
BAIL_ON_FAILURE(hr);
}
else {
vVar.vt = VT_BSTR;
hr = ADsAllocString( pPropertyInfo->szDefault, &(vVar.bstrVal));
BAIL_ON_FAILURE(hr);
}
hr = CPropertyAttribute::CreatePropertyAttribute(
IID_IISPropertyAttribute,
(VOID**)&pPropAttrib
);
BAIL_ON_FAILURE(hr);
hr = ((CPropertyAttribute*)pPropAttrib)->InitFromRawData(
(LPWSTR) wchName,
dwMetaId,
pPropertyInfo->dwUserGroup,
pPropertyInfo->dwMetaFlags,
&vVar
);
BAIL_ON_FAILURE(hr);
*ppObject = (IDispatch*)pPropAttrib;
error:
VariantClear(&vVar);
RRETURN(hr);
}
STDMETHODIMP
CIISSchema::PutSchemaPropertyAttributes(
THIS_ IDispatch * pObject
)
{
RRETURN(E_NOTIMPL);
}