//*************************************************************************** // // ENUM.CPP // // Module: WBEM Instance provider // // Purpose: Enumerate metabase tree // // Copyright (c)1998 Microsoft Corporation, All Rights Reserved // //*************************************************************************** #include "iisprov.h" /////////////////////////////////////// // // CEnum class // /////////////////////////////////////// CEnum::CEnum() { m_pInstMgr = NULL; m_pNamespace = NULL; m_pAssociation = NULL; m_pParsedObject = NULL; m_hKey = NULL; } CEnum::~CEnum() { if(m_hKey) m_metabase.CloseKey(m_hKey); if(m_pInstMgr) delete m_pInstMgr; } void CEnum::Init( IWbemObjectSink FAR* a_pHandler, CWbemServices* a_pNamespace, ParsedObjectPath* a_pParsedObject, LPWSTR a_pszKey, WMI_ASSOCIATION* a_pAssociation ) { if (!a_pHandler || !a_pNamespace || !a_pParsedObject) throw WBEM_E_FAILED; m_pInstMgr = new CWbemInstanceMgr(a_pHandler); THROW_ON_FALSE(m_pInstMgr); m_pNamespace = a_pNamespace; m_pAssociation = a_pAssociation; m_pParsedObject = a_pParsedObject; m_hKey = m_metabase.OpenKey(a_pszKey, false); // read only } void CEnum::SetObjectPath( LPCWSTR a_pszPropertyName, LPCWSTR a_pszObjectPath, IWbemClassObject* a_pObj ) { _bstr_t t_bstr(a_pszPropertyName); _variant_t t_v(a_pszObjectPath); HRESULT t_hr = a_pObj->Put(t_bstr, 0, &t_v, 0); THROW_ON_ERROR(t_hr); } void CEnum::PingObject() { IWbemClassObject* t_pObj = NULL; try { CUtils obj; HRESULT hr = obj.GetObjectAsync(m_pNamespace, &t_pObj, m_pParsedObject, m_metabase); if(SUCCEEDED(hr) && t_pObj) { m_pInstMgr->Indicate(t_pObj); t_pObj->Release(); } } catch(...) { } } void CEnum::PingAssociation( LPCWSTR a_pszLeftKeyPath ) { HRESULT t_hr; IWbemClassObject* t_pObj = NULL; IWbemClassObject* t_pClass = NULL; LPWSTR t_pszObjectPath = NULL; CObjectPathParser t_PathParser(e_ParserAcceptRelativeNamespace); WCHAR t_LeftName[20]; WCHAR t_RightName[20]; if(m_pAssociation->at == at_ElementSetting) { lstrcpyW(t_LeftName, L"Element"); lstrcpyW(t_RightName, L"Setting"); } else if(m_pAssociation->at == at_Component) { lstrcpyW(t_LeftName, L"GroupComponent"); lstrcpyW(t_RightName, L"PartComponent"); } else return; try { t_hr = m_pNamespace->GetObject( m_pAssociation->pszAssociationName, 0, NULL, &t_pClass, NULL ); THROW_ON_ERROR(t_hr); t_hr = t_pClass->SpawnInstance(0, &t_pObj); t_pClass->Release(); THROW_ON_ERROR(t_hr); // // first right side // if (!m_pParsedObject->SetClassName(m_pAssociation->pcRight->pszClassName)) throw WBEM_E_FAILED; if (t_PathParser.Unparse(m_pParsedObject,&t_pszObjectPath)) throw WBEM_E_FAILED; SetObjectPath(t_RightName, t_pszObjectPath, t_pObj); if(t_pszObjectPath) { delete [] t_pszObjectPath; t_pszObjectPath = NULL; } // // then left side // if (m_pAssociation->at == at_Component || m_pAssociation->fFlags & ASSOC_EXTRAORDINARY) { // clear keyref first m_pParsedObject->ClearKeys(); // add a keyref _variant_t t_vt; if(m_pAssociation->pcLeft->eKeyType == IIsComputer) t_vt = L"LM"; // IIsComputer.Name = "LM" else t_vt = a_pszLeftKeyPath; THROW_ON_FALSE(m_pParsedObject->AddKeyRef(m_pAssociation->pcLeft->pszKeyName,&t_vt)); } if (!m_pParsedObject->SetClassName(m_pAssociation->pcLeft->pszClassName)) throw WBEM_E_FAILED; if (t_PathParser.Unparse(m_pParsedObject,&t_pszObjectPath)) throw WBEM_E_FAILED; SetObjectPath(t_LeftName, t_pszObjectPath, t_pObj); if(t_pszObjectPath) { delete [] t_pszObjectPath; t_pszObjectPath = NULL; } if(t_pObj) { m_pInstMgr->Indicate(t_pObj); t_pObj->Release(); t_pObj = NULL; } } catch (...) { if(t_pszObjectPath) delete [] t_pszObjectPath; if(t_pObj) t_pObj->Release(); } } void CEnum::DoPing( LPCWSTR a_pszKeyName, LPCWSTR a_pszKeyPath, LPCWSTR a_pszParentKeyPath ) { // add keyref _variant_t t_v(a_pszKeyPath); THROW_ON_FALSE(m_pParsedObject->AddKeyRef(a_pszKeyName,&t_v)); // ping if (!m_pAssociation) PingObject(); else PingAssociation(a_pszParentKeyPath); // clear keyref m_pParsedObject->ClearKeys(); } void CEnum::Recurse( LPCWSTR a_pszMetabasePath, enum_KEY_TYPE a_eParentKeyType, LPCWSTR a_pszLeftPath, LPCWSTR a_pszKeyName, enum_KEY_TYPE a_eKeyType ) { DWORD t_i = 0; HRESULT t_hr; WCHAR t_szSubKey[METADATA_MAX_NAME_LEN]; enum_KEY_TYPE t_eSubKeyType; do { t_eSubKeyType = a_eKeyType; t_hr = m_metabase.EnumKeys( m_hKey, a_pszMetabasePath, t_szSubKey, &t_i, t_eSubKeyType ); t_i++; if( t_hr == ERROR_SUCCESS) { _bstr_t t_bstrMetabasePath; if(a_pszMetabasePath) { t_bstrMetabasePath = a_pszMetabasePath; t_bstrMetabasePath += L"/"; } t_bstrMetabasePath += t_szSubKey; if( t_eSubKeyType == a_eKeyType && !( m_pAssociation && (m_pAssociation->at == at_Component || m_pAssociation->fFlags & ASSOC_EXTRAORDINARY) && m_pAssociation->pcLeft->eKeyType != a_eParentKeyType ) ) { DoPing(a_pszKeyName, t_bstrMetabasePath, a_pszLeftPath); } else if( a_eKeyType == TYPE_AdminACL || // AdminACL a_eKeyType == TYPE_AdminACE ) { if( !(m_pAssociation && m_pAssociation->at == at_AdminACL && m_pAssociation->pcLeft->eKeyType != t_eSubKeyType && lstrcmpiW(m_pAssociation->pszAssociationName, L"IIs_AdminACL_ACE") ) ) { DoPingAdminACL(a_eKeyType, a_pszKeyName, t_bstrMetabasePath); } } else if( a_eKeyType == TYPE_IPSecurity ) // IPSecurity { if( !(m_pAssociation && m_pAssociation->at == at_IPSecurity && m_pAssociation->pcLeft->eKeyType != t_eSubKeyType ) ) { DoPingIPSecurity(a_eKeyType, a_pszKeyName, t_bstrMetabasePath); } } // recusive if(ContinueRecurse(t_eSubKeyType, a_eKeyType)) { LPCWSTR t_pszLeftPath = a_pszLeftPath; // if the association is extraordinary (see schema.h for explanation) if (m_pAssociation && m_pAssociation->fFlags & ASSOC_EXTRAORDINARY) { // When the left endpoint of the assoc. is found freeze the // parent key type and path. if (a_pszLeftPath != NULL || (a_eParentKeyType == IIsComputer && a_eParentKeyType == m_pAssociation->pcLeft->eKeyType)) { t_eSubKeyType = a_eParentKeyType; } if (t_eSubKeyType == m_pAssociation->pcLeft->eKeyType && a_pszLeftPath == NULL) { t_pszLeftPath = t_bstrMetabasePath; } } else { // this is the parent path, because the next thing we are doing is // calling recurse. t_pszLeftPath = t_bstrMetabasePath; } Recurse(t_bstrMetabasePath, t_eSubKeyType, t_pszLeftPath, a_pszKeyName, a_eKeyType); } } }while(t_hr == ERROR_SUCCESS); } // DESC: You are looking for a_eKeyType by traversing thru the tree. You are // currently at a_eParentKeyType and need to determine if you should keep // on going. // COMM: This seems very similar to CMetabase::CheckKey bool CEnum::ContinueRecurse( enum_KEY_TYPE a_eParentKeyType, enum_KEY_TYPE a_eKeyType ) { bool bRet = false; switch(a_eKeyType) { case IIsLogModule: if( a_eParentKeyType == IIsLogModules ) bRet = true; break; case IIsFtpInfo: if( a_eParentKeyType == IIsFtpService ) bRet = true; break; case IIsFtpServer: if( a_eParentKeyType == IIsFtpService ) bRet = true; break; case IIsFtpVirtualDir: if( a_eParentKeyType == IIsFtpService || a_eParentKeyType == IIsFtpServer || a_eParentKeyType == IIsFtpVirtualDir ) bRet = true; break; case IIsWebInfo: if( a_eParentKeyType == IIsWebService ) bRet = true; break; case IIsFilters: if( a_eParentKeyType == IIsWebService || a_eParentKeyType == IIsWebServer ) bRet = true; break; case IIsFilter: if( a_eParentKeyType == IIsWebService || a_eParentKeyType == IIsWebServer || a_eParentKeyType == IIsFilters ) bRet = true; break; case IIsCompressionSchemes: if( a_eParentKeyType == IIsWebService || a_eParentKeyType == IIsWebServer || a_eParentKeyType == IIsFilters ) bRet = true; break; case IIsCompressionScheme: if( a_eParentKeyType == IIsWebService || a_eParentKeyType == IIsWebServer || a_eParentKeyType == IIsFilters || a_eParentKeyType == IIsCompressionSchemes ) bRet = true; break; case IIsWebServer: if( a_eParentKeyType == IIsWebService ) bRet = true; break; case IIsCertMapper: if( a_eParentKeyType == IIsWebService || a_eParentKeyType == IIsWebServer ) bRet = true; break; case IIsWebVirtualDir: if( a_eParentKeyType == IIsWebService || a_eParentKeyType == IIsWebServer || a_eParentKeyType == IIsWebVirtualDir || a_eParentKeyType == IIsWebDirectory ) bRet = true; break; case IIsWebDirectory: if( a_eParentKeyType == IIsWebService || a_eParentKeyType == IIsWebServer || a_eParentKeyType == IIsWebVirtualDir || a_eParentKeyType == IIsWebDirectory ) bRet = true; break; case IIsWebFile: if( a_eParentKeyType == IIsWebService || a_eParentKeyType == IIsWebServer || a_eParentKeyType == IIsWebVirtualDir || a_eParentKeyType == IIsWebDirectory ) bRet = true; break; case TYPE_AdminACL: case TYPE_AdminACE: if( a_eParentKeyType == IIsWebService || a_eParentKeyType == IIsWebServer || a_eParentKeyType == IIsWebVirtualDir || a_eParentKeyType == IIsWebDirectory || a_eParentKeyType == IIsFtpService || a_eParentKeyType == IIsFtpServer || a_eParentKeyType == IIsFtpVirtualDir ) bRet = true; break; case TYPE_IPSecurity: if( a_eParentKeyType == IIsWebService || a_eParentKeyType == IIsWebServer || a_eParentKeyType == IIsWebVirtualDir || a_eParentKeyType == IIsWebDirectory || a_eParentKeyType == IIsFtpService || a_eParentKeyType == IIsFtpServer || a_eParentKeyType == IIsFtpVirtualDir ) bRet = true; break; default: break; } return bRet; } void CEnum::DoPingAdminACL( enum_KEY_TYPE a_eKeyType, LPCWSTR a_pszKeyName, LPCWSTR a_pszKeyPath ) { // add keyref _variant_t t_v(a_pszKeyPath); THROW_ON_FALSE(m_pParsedObject->AddKeyRef(a_pszKeyName,&t_v)); if(a_eKeyType == TYPE_AdminACE) { EnumACE(a_pszKeyPath); } else if(a_eKeyType == TYPE_AdminACL) { // ping if (!m_pAssociation) PingObject(); else PingAssociationAdminACL(a_pszKeyPath); } // clear keyref m_pParsedObject->ClearKeys(); } // for AdminACL void CEnum::EnumACE( LPCWSTR pszKeyPath ) { HRESULT hr = S_OK; _variant_t var; IEnumVARIANT* pEnum = NULL; ULONG lFetch; BSTR bstrTrustee; IDispatch* pDisp = NULL; IADsAccessControlEntry* pACE = NULL; _bstr_t bstrMbPath; WMI_CLASS* pWMIClass; // get the metabase path of the object BOOL fClass = FALSE; if(m_pAssociation) fClass = CUtils::GetClass(m_pAssociation->pcLeft->pszClassName,&pWMIClass); else fClass = CUtils::GetClass(m_pParsedObject->m_pClass,&pWMIClass); if(!fClass) return; CUtils::GetMetabasePath(NULL,m_pParsedObject,pWMIClass,bstrMbPath); // open ADSI CAdminACL objACL; hr = objACL.OpenSD(bstrMbPath); if(SUCCEEDED(hr)) hr = objACL.GetACEEnum(&pEnum); if ( FAILED(hr) ) return; ////////////////////////////////////////////// // Enumerate ACEs ////////////////////////////////////////////// hr = pEnum->Next( 1, &var, &lFetch ); while( hr == S_OK ) { if ( lFetch == 1 ) { if ( VT_DISPATCH != V_VT(&var) ) { break; } pDisp = V_DISPATCH(&var); ///////////////////////////// // Get the individual ACE ///////////////////////////// hr = pDisp->QueryInterface( IID_IADsAccessControlEntry, (void**)&pACE ); if ( SUCCEEDED(hr) ) { hr = pACE->get_Trustee(&bstrTrustee); if( SUCCEEDED(hr) ) { // add keyref _variant_t t_v(bstrTrustee); //m_pParsedObject->RemoveKeyRef(L"Trustee"); THROW_ON_FALSE(m_pParsedObject->AddKeyRefEx(L"Trustee",&t_v)); // ping if (!m_pAssociation) PingObject(); else PingAssociationAdminACL(pszKeyPath); } SysFreeString(bstrTrustee); pACE->Release(); } } hr = pEnum->Next( 1, &var, &lFetch ); } pEnum->Release(); } void CEnum::PingAssociationAdminACL( LPCWSTR a_pszLeftKeyPath ) { HRESULT t_hr; IWbemClassObject* t_pObj = NULL; IWbemClassObject* t_pClass = NULL; LPWSTR t_pszObjectPath = NULL; CObjectPathParser t_PathParser(e_ParserAcceptRelativeNamespace); WCHAR t_LeftName[20]; WCHAR t_RightName[20]; _bstr_t bstrMbPath; WMI_CLASS* pWMIClass; if(m_pAssociation->at != at_AdminACL) return; // get the metabase path of the object if (CUtils::GetClass(m_pAssociation->pcLeft->pszClassName,&pWMIClass)) { CUtils::GetMetabasePath(NULL,m_pParsedObject,pWMIClass,bstrMbPath); } else return; // check if AdminACL existed CAdminACL objACL; t_hr = objACL.OpenSD(bstrMbPath); objACL.CloseSD(); if(FAILED(t_hr)) return; // set the key name lstrcpyW(t_LeftName, L"GroupComponent"); lstrcpyW(t_RightName, L"PartComponent"); try { t_hr = m_pNamespace->GetObject( m_pAssociation->pszAssociationName, 0, NULL, &t_pClass, NULL ); THROW_ON_ERROR(t_hr); t_hr = t_pClass->SpawnInstance(0, &t_pObj); t_pClass->Release(); THROW_ON_ERROR(t_hr); // // first right side // if (!m_pParsedObject->SetClassName(m_pAssociation->pcRight->pszClassName)) throw WBEM_E_FAILED; if (t_PathParser.Unparse(m_pParsedObject,&t_pszObjectPath)) throw WBEM_E_FAILED; SetObjectPath(t_RightName, t_pszObjectPath, t_pObj); if(t_pszObjectPath) { delete [] t_pszObjectPath; t_pszObjectPath = NULL; } // // then left side // if(!lstrcmpiW(m_pAssociation->pszAssociationName, L"IIs_AdminACL_ACE")) { // clear keyref first m_pParsedObject->ClearKeys(); // add a keyref _variant_t t_vt = a_pszLeftKeyPath; THROW_ON_FALSE(m_pParsedObject->AddKeyRef(m_pAssociation->pcLeft->pszKeyName,&t_vt)); } if (!m_pParsedObject->SetClassName(m_pAssociation->pcLeft->pszClassName)) throw WBEM_E_FAILED; if (t_PathParser.Unparse(m_pParsedObject,&t_pszObjectPath)) throw WBEM_E_FAILED; SetObjectPath(t_LeftName, t_pszObjectPath, t_pObj); if(t_pszObjectPath) { delete [] t_pszObjectPath; t_pszObjectPath = NULL; } if(t_pObj) { m_pInstMgr->Indicate(t_pObj); t_pObj->Release(); t_pObj = NULL; } } catch (...) { if(t_pszObjectPath) delete [] t_pszObjectPath; if(t_pObj) t_pObj->Release(); } } // for IPSecurity void CEnum::DoPingIPSecurity( enum_KEY_TYPE a_eKeyType, LPCWSTR a_pszKeyName, LPCWSTR a_pszKeyPath ) { // add keyref _variant_t t_v(a_pszKeyPath); THROW_ON_FALSE(m_pParsedObject->AddKeyRef(a_pszKeyName,&t_v)); // ping if (!m_pAssociation) PingObject(); else PingAssociationIPSecurity(a_pszKeyPath); // clear keyref m_pParsedObject->ClearKeys(); } // for IPSecurity void CEnum::PingAssociationIPSecurity( LPCWSTR a_pszLeftKeyPath ) { HRESULT t_hr; IWbemClassObject* t_pObj = NULL; IWbemClassObject* t_pClass = NULL; LPWSTR t_pszObjectPath = NULL; CObjectPathParser t_PathParser(e_ParserAcceptRelativeNamespace); WCHAR t_LeftName[20]; WCHAR t_RightName[20]; _bstr_t bstrMbPath; WMI_CLASS* pWMIClass; if(m_pAssociation->at != at_IPSecurity) return; // get the metabase path of the object if (CUtils::GetClass(m_pAssociation->pcLeft->pszClassName,&pWMIClass)) { CUtils::GetMetabasePath(NULL,m_pParsedObject,pWMIClass,bstrMbPath); } else return; // check if IPSecurity existed CIPSecurity objIPsec; t_hr = objIPsec.OpenSD(bstrMbPath); objIPsec.CloseSD(); if(FAILED(t_hr)) return; // set the key name lstrcpyW(t_LeftName, L"Element"); lstrcpyW(t_RightName, L"Setting"); try { t_hr = m_pNamespace->GetObject( m_pAssociation->pszAssociationName, 0, NULL, &t_pClass, NULL ); THROW_ON_ERROR(t_hr); t_hr = t_pClass->SpawnInstance(0, &t_pObj); t_pClass->Release(); THROW_ON_ERROR(t_hr); // // first right side // if (!m_pParsedObject->SetClassName(m_pAssociation->pcRight->pszClassName)) throw WBEM_E_FAILED; if (t_PathParser.Unparse(m_pParsedObject,&t_pszObjectPath)) throw WBEM_E_FAILED; SetObjectPath(t_RightName, t_pszObjectPath, t_pObj); if(t_pszObjectPath) { delete [] t_pszObjectPath; t_pszObjectPath = NULL; } // // then left side // if (!m_pParsedObject->SetClassName(m_pAssociation->pcLeft->pszClassName)) throw WBEM_E_FAILED; if (t_PathParser.Unparse(m_pParsedObject,&t_pszObjectPath)) throw WBEM_E_FAILED; SetObjectPath(t_LeftName, t_pszObjectPath, t_pObj); if(t_pszObjectPath) { delete [] t_pszObjectPath; t_pszObjectPath = NULL; } if(t_pObj) { m_pInstMgr->Indicate(t_pObj); t_pObj->Release(); t_pObj = NULL; } } catch (...) { if(t_pszObjectPath) delete [] t_pszObjectPath; if(t_pObj) t_pObj->Release(); } }