//*************************************************************************** // // adminacl.cpp // // Module: WBEM Instance provider // // Purpose: IIS AdminACL class // // Copyright (c)1998 Microsoft Corporation, All Rights Reserved // //*************************************************************************** #include "iisprov.h" CAdminACL::CAdminACL() { m_pADs = NULL; m_pSD = NULL; m_pDACL = NULL; } CAdminACL::~CAdminACL() { CloseSD(); } void CAdminACL::CloseSD() { if(m_pDACL) { m_pDACL->Release(); m_pDACL = NULL; } if(m_pSD) { m_pSD->Release(); m_pSD = NULL; } if(m_pADs) { m_pADs->Release(); m_pADs = NULL; } } HRESULT CAdminACL::GetObjectAsync( IWbemClassObject* pObj, ParsedObjectPath* pParsedObject, WMI_CLASS* pWMIClass ) { if(!m_pSD || !m_pSD || !m_pDACL) return E_UNEXPECTED; HRESULT hr = S_OK; if( pWMIClass->eKeyType == TYPE_AdminACL ) { hr = PingAdminACL(pObj); } else if( pWMIClass->eKeyType == TYPE_AdminACE ) { _bstr_t bstrTrustee; GetTrustee(pObj, pParsedObject, bstrTrustee); hr = GetACE(pObj, bstrTrustee); } else hr = E_INVALIDARG; return hr; } HRESULT CAdminACL::DeleteObjectAsync(ParsedObjectPath* pParsedObject) { HRESULT hr = S_OK; _bstr_t bstrTrustee; // get the trustee from key GetTrustee(NULL, pParsedObject, bstrTrustee); // remove the ACE hr = RemoveACE(bstrTrustee); // set the modified AdminACL back into the metabase if(SUCCEEDED(hr)) hr = SetSD(); return hr; } HRESULT CAdminACL::PutObjectAsync( IWbemClassObject* pObj, ParsedObjectPath* pParsedObject, WMI_CLASS* pWMIClass ) { if(!m_pSD || !m_pSD || !m_pDACL) return E_UNEXPECTED; HRESULT hr; if( pWMIClass->eKeyType == TYPE_AdminACL ) { hr = SetAdminACL(pObj); } else if( pWMIClass->eKeyType == TYPE_AdminACE ) { _bstr_t bstrTrustee; GetTrustee(NULL, pParsedObject, bstrTrustee); BOOL fAceExisted = FALSE; hr = UpdateACE(pObj, bstrTrustee, fAceExisted); if(fAceExisted == FALSE) hr = AddACE(pObj, bstrTrustee); } else hr = E_INVALIDARG; // set the modified AdminACL back into the metabase if(SUCCEEDED(hr)) hr = SetSD(); return hr; } HRESULT CAdminACL::PingAdminACL( IWbemClassObject* pObj ) { _variant_t vt; BSTR bstr; long lVal; HRESULT hr; // Owner hr = m_pSD->get_Owner(&bstr); if(SUCCEEDED(hr)) { vt = bstr; hr = pObj->Put(L"Owner", 0, &vt, 0); SysFreeString(bstr); } // Group if(SUCCEEDED(hr)) hr = m_pSD->get_Group(&bstr); if(SUCCEEDED(hr)) { vt = bstr; hr = pObj->Put(L"Group", 0, &vt, 0); SysFreeString(bstr); } // ControlFlags if(SUCCEEDED(hr)) hr = m_pSD->get_Control(&lVal); if(SUCCEEDED(hr)) { vt.vt = VT_I4; vt.lVal = lVal; hr = pObj->Put(L"ControlFlags", 0, &vt, 0); } return hr; } HRESULT CAdminACL::SetAdminACL( IWbemClassObject* pObj ) { _variant_t vt; HRESULT hr; // Owner hr = pObj->Get(L"Owner", 0, &vt, NULL, NULL); if(SUCCEEDED(hr) && vt.vt == VT_BSTR) hr = m_pSD->put_Owner(vt.bstrVal); // Owner if(SUCCEEDED(hr)) hr = pObj->Get(L"Group", 0, &vt, NULL, NULL); if(SUCCEEDED(hr) && vt.vt == VT_BSTR) hr = m_pSD->put_Group(vt.bstrVal); // ControlFlags if(SUCCEEDED(hr)) hr = pObj->Get(L"ControlFlags", 0, &vt, NULL, NULL); if(SUCCEEDED(hr) && vt.vt == VT_I4) hr = m_pSD->put_Control(vt.lVal); return hr; } HRESULT CAdminACL::OpenSD(_bstr_t bstrAdsPath) { _variant_t var; HRESULT hr; IDispatch* pDisp = NULL; // close SD interface first CloseSD(); hr = GetAdsPath(bstrAdsPath); if(FAILED(hr)) return hr; // get m_pADs hr = ADsGetObject( bstrAdsPath, IID_IADs, (void**)&m_pADs ); if(FAILED(hr)) return hr; // get m_pSD hr = m_pADs->Get(L"AdminACL",&var); if(FAILED(hr)) return hr; hr = V_DISPATCH(&var)->QueryInterface( IID_IADsSecurityDescriptor, (void**)&m_pSD ); if(FAILED(hr)) return hr; // get m_pDACL hr = m_pSD->get_DiscretionaryAcl(&pDisp); if(FAILED(hr)) return hr; hr = pDisp->QueryInterface( IID_IADsAccessControlList, (void**)&m_pDACL ); pDisp->Release(); return hr; } HRESULT CAdminACL::SetSD() { _variant_t var; HRESULT hr; IDispatch* pDisp = NULL; // put m_pDACL hr = m_pDACL->QueryInterface( IID_IDispatch, (void**)&pDisp ); if(FAILED(hr)) return hr; hr = m_pSD->put_DiscretionaryAcl(pDisp); pDisp->Release(); if(FAILED(hr)) return hr; // put AdminACL hr = m_pSD->QueryInterface( IID_IDispatch, (void**)&pDisp ); if(FAILED(hr)) return hr; var.vt = VT_DISPATCH; var.pdispVal = pDisp; hr = m_pADs->Put(L"AdminACL",var); // pDisp will be released by this call Put(). if(FAILED(hr)) return hr; // Commit the change to the active directory hr = m_pADs->SetInfo(); return hr; } HRESULT CAdminACL::GetAdsPath(_bstr_t& bstrAdsPath) { WCHAR* p = new WCHAR[bstrAdsPath.length() + 1]; if(p == NULL) return E_OUTOFMEMORY; lstrcpyW(p, bstrAdsPath); bstrAdsPath = L"IIS://LocalHost"; // trim first three charaters "/LM" bstrAdsPath += (p+3); delete [] p; return S_OK; } HRESULT CAdminACL::PingACE( IWbemClassObject* pObj, IADsAccessControlEntry* pACE ) { _variant_t vt; BSTR bstr; long lVal; HRESULT hr; // AccessMask hr = pACE->get_AccessMask(&lVal); if(SUCCEEDED(hr)) { vt.vt = VT_I4; vt.lVal = lVal; hr = pObj->Put(L"AccessMask", 0, &vt, 0); } // AceType if(SUCCEEDED(hr)) hr = pACE->get_AceType(&lVal); if(SUCCEEDED(hr)) { vt.vt = VT_I4; vt.lVal = lVal; hr = pObj->Put(L"AceType", 0, &vt, 0); } // AceFlags if(SUCCEEDED(hr)) hr = pACE->get_AceFlags(&lVal); if(SUCCEEDED(hr)) { vt.vt = VT_I4; vt.lVal = lVal; hr = pObj->Put(L"AceFlags", 0, &vt, 0); } // Flags if(SUCCEEDED(hr)) hr = pACE->get_Flags(&lVal); if(SUCCEEDED(hr)) { vt.vt = VT_I4; vt.lVal = lVal; hr = pObj->Put(L"Flags", 0, &vt, 0); } // ObjectType if(SUCCEEDED(hr)) hr = pACE->get_ObjectType(&bstr); if(SUCCEEDED(hr)) { vt = bstr; hr = pObj->Put(L"ObjectType", 0, &vt, 0); SysFreeString(bstr); } // InheritedObjectType if(SUCCEEDED(hr)) hr = pACE->get_InheritedObjectType(&bstr); if(SUCCEEDED(hr)) { vt = bstr; hr = pObj->Put(L"InheritedObjectType", 0, &vt, 0); SysFreeString(bstr); } return hr; } HRESULT CAdminACL::GetACE( IWbemClassObject* pObj, _bstr_t& bstrTrustee ) { HRESULT hr = S_OK; _variant_t var; IEnumVARIANT* pEnum = NULL; ULONG lFetch; BSTR bstr; IDispatch *pDisp = NULL; IADsAccessControlEntry *pACE = NULL; hr = GetACEEnum(&pEnum); if ( FAILED(hr) ) return hr; ////////////////////////////////////////////// // Enumerate ACEs ////////////////////////////////////////////// hr = pEnum->Next( 1, &var, &lFetch ); while( hr == S_OK ) { if ( lFetch == 1 ) { if ( VT_DISPATCH != V_VT(&var) ) { hr = E_UNEXPECTED; break; } pDisp = V_DISPATCH(&var); ///////////////////////////// // Get the individual ACE ///////////////////////////// hr = pDisp->QueryInterface( IID_IADsAccessControlEntry, (void**)&pACE ); if ( SUCCEEDED(hr) ) { hr = pACE->get_Trustee(&bstr); if( SUCCEEDED(hr) && !lstrcmpiW(bstr, bstrTrustee) ) { hr = PingACE(pObj, pACE); SysFreeString(bstr); pACE->Release(); break; } SysFreeString(bstr); pACE->Release(); } } hr = pEnum->Next( 1, &var, &lFetch ); } pEnum->Release(); return hr; } HRESULT CAdminACL::RemoveACE( _bstr_t& bstrTrustee ) { HRESULT hRemoved = WBEM_E_INVALID_PARAMETER; HRESULT hr = S_OK; _variant_t var; IEnumVARIANT* pEnum = NULL; ULONG lFetch; BSTR bstr; IDispatch *pDisp = NULL; IADsAccessControlEntry *pACE = NULL; hr = GetACEEnum(&pEnum); if ( FAILED(hr) ) return hr; ////////////////////////////////////////////// // Enumerate ACEs ////////////////////////////////////////////// hr = pEnum->Next( 1, &var, &lFetch ); while( hr == S_OK ) { if ( lFetch == 1 ) { if ( VT_DISPATCH != V_VT(&var) ) { hr = E_UNEXPECTED; break; } pDisp = V_DISPATCH(&var); ///////////////////////////// // Get the individual ACE ///////////////////////////// hr = pDisp->QueryInterface( IID_IADsAccessControlEntry, (void**)&pACE ); if ( SUCCEEDED(hr) ) { hr = pACE->get_Trustee(&bstr); if( SUCCEEDED(hr) && !lstrcmpiW(bstr, bstrTrustee) ) { // remove ACE hr = pACE->QueryInterface(IID_IDispatch,(void**)&pDisp); if ( SUCCEEDED(hr) ) { hRemoved = m_pDACL->RemoveAce(pDisp); pDisp->Release(); } SysFreeString(bstr); pACE->Release(); break; } SysFreeString(bstr); pACE->Release(); } } hr = pEnum->Next( 1, &var, &lFetch ); } pEnum->Release(); return hRemoved; } // parse ParsedObjectPath to get the Trustee key void CAdminACL::GetTrustee( IWbemClassObject* pObj, ParsedObjectPath* pPath, _bstr_t& bstrTrustee ) { KeyRef* pkr; WCHAR* pszKey = L"Trustee"; pkr = CUtils::GetKey(pPath, pszKey); if(pkr == NULL) throw WBEM_E_INVALID_OBJECT; bstrTrustee = pkr->m_vValue; if (pObj) { _bstr_t bstr = pkr->m_pName; HRESULT hr = pObj->Put(bstr, 0, &pkr->m_vValue, 0); THROW_ON_ERROR(hr); } } HRESULT CAdminACL::GetACEEnum( IEnumVARIANT** pEnum ) { HRESULT hr = S_OK; LPUNKNOWN pUnk = NULL; if(!pEnum) return E_INVALIDARG; if(*pEnum) (*pEnum)->Release(); hr = m_pDACL->get__NewEnum( &pUnk ); if ( SUCCEEDED(hr) ) { hr = pUnk->QueryInterface( IID_IEnumVARIANT, (void**) pEnum ); } return hr; } // addd a ACE HRESULT CAdminACL::AddACE( IWbemClassObject* pObj, _bstr_t& bstrTrustee ) { HRESULT hr = m_pDACL->put_AclRevision(ADS_SD_REVISION_DS); if(FAILED(hr)) return hr; // create a ACE IADsAccessControlEntry* pACE = NULL; hr = NewACE( pObj, bstrTrustee, &pACE ); if(FAILED(hr)) return hr; // add the ACE IDispatch* pDisp = NULL; hr = pACE->QueryInterface(IID_IDispatch,(void**)&pDisp); if(SUCCEEDED(hr)) { hr = m_pDACL->AddAce(pDisp); pDisp->Release(); } pACE->Release(); return hr; } //////////////////////////////////// // function to create an ACE //////////////////////////////////// HRESULT CAdminACL::NewACE( IWbemClassObject* pObj, _bstr_t& bstrTrustee, IADsAccessControlEntry** ppACE ) { if(!ppACE) return E_INVALIDARG; HRESULT hr; hr = CoCreateInstance( CLSID_AccessControlEntry, NULL, CLSCTX_INPROC_SERVER, IID_IADsAccessControlEntry, (void**)ppACE ); // Trustee _variant_t vt; if(SUCCEEDED(hr)) hr = (*ppACE)->put_Trustee(bstrTrustee); if(SUCCEEDED(hr)) hr = SetDataOfACE(pObj, *ppACE); return hr; } HRESULT CAdminACL::SetDataOfACE( IWbemClassObject* pObj, IADsAccessControlEntry* pACE ) { HRESULT hr; _variant_t vt; // AccessMask hr = pObj->Get(L"AccessMask", 0, &vt, NULL, NULL); if(SUCCEEDED(hr) && vt.vt == VT_I4) hr = pACE->put_AccessMask(vt.lVal); // AceType if(SUCCEEDED(hr)) hr = pObj->Get(L"AceType", 0, &vt, NULL, NULL); if(SUCCEEDED(hr) && vt.vt == VT_I4) hr = pACE->put_AceType(vt.lVal); // AceFlags if(SUCCEEDED(hr)) hr = pObj->Get(L"AceFlags", 0, &vt, NULL, NULL); if(SUCCEEDED(hr) && vt.vt == VT_I4) hr = pACE->put_AceFlags(vt.lVal); // Flags if(SUCCEEDED(hr)) hr = pObj->Get(L"Flags", 0, &vt, NULL, NULL); if(SUCCEEDED(hr) && vt.vt == VT_I4) hr = pACE->put_Flags(vt.lVal); // ObjectType if(SUCCEEDED(hr)) hr = pObj->Get(L"ObjectType", 0, &vt, NULL, NULL); if(SUCCEEDED(hr) && vt.vt == VT_BSTR) hr = pACE->put_ObjectType(vt.bstrVal); // InheritedObjectType if(SUCCEEDED(hr)) hr = pObj->Get(L"InheritedObjectType", 0, &vt, NULL, NULL); if(SUCCEEDED(hr) && vt.vt == VT_BSTR) hr = pACE->put_InheritedObjectType(vt.bstrVal); return hr; } HRESULT CAdminACL::UpdateACE( IWbemClassObject* pObj, _bstr_t& bstrTrustee, BOOL& fAceExisted ) { HRESULT hr = S_OK; _variant_t var; IEnumVARIANT* pEnum = NULL; ULONG lFetch; BSTR bstr; IDispatch *pDisp = NULL; IADsAccessControlEntry *pACE = NULL; fAceExisted = FALSE; hr = GetACEEnum(&pEnum); if ( FAILED(hr) ) return hr; ////////////////////////////////////////////// // Enumerate ACEs ////////////////////////////////////////////// hr = pEnum->Next( 1, &var, &lFetch ); while( hr == S_OK ) { if ( lFetch == 1 ) { if ( VT_DISPATCH != V_VT(&var) ) { hr = E_UNEXPECTED; break; } pDisp = V_DISPATCH(&var); ///////////////////////////// // Get the individual ACE ///////////////////////////// hr = pDisp->QueryInterface( IID_IADsAccessControlEntry, (void**)&pACE ); if ( SUCCEEDED(hr) ) { hr = pACE->get_Trustee(&bstr); if( SUCCEEDED(hr) && !lstrcmpiW(bstr, bstrTrustee) ) { fAceExisted = TRUE; // Update the data of the ACE hr = SetDataOfACE(pObj, pACE); SysFreeString(bstr); pACE->Release(); break; } SysFreeString(bstr); pACE->Release(); } } hr = pEnum->Next( 1, &var, &lFetch ); } pEnum->Release(); return hr; }