//--------------------------------------------------------------------------- // // 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; CCredentials localCred; hr = AllocateSchemaObject(&pSchema); BAIL_ON_FAILURE(hr); hr = InitServerInfo(localCred, 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 = (DWORD)(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 // CCredentials localCred; hr = OpenAdminBaseKey( localCred, _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 // CCredentials localCred; hr = OpenAdminBaseKey( localCred, _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; if (pSchema) { delete pSchema; } } 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); }