//================================================================= // // assoc.cpp -- Generic association class // // Copyright 1999 Microsoft Corporation // //================================================================= #include #include "precomp.h" #include #include "Assoc.h" CAssociation::CAssociation( LPCWSTR pwszClassName, LPCWSTR pwszNamespaceName, LPCWSTR pwszLeftClassName, LPCWSTR pwszRightClassName, LPCWSTR pwszLeftPropertyName, LPCWSTR pwszRightPropertyName ) : Provider(pwszClassName, pwszNamespaceName) { ASSERT_BREAK( ( pwszClassName != NULL ) && ( pwszLeftClassName != NULL ) && ( pwszRightClassName != NULL) && ( pwszLeftPropertyName != NULL ) && ( pwszRightPropertyName != NULL) ); m_pwszLeftClassName = pwszLeftClassName; m_pwszRightClassName = pwszRightClassName; m_pwszLeftPropertyName = pwszLeftPropertyName; m_pwszRightPropertyName = pwszRightPropertyName; } CAssociation::~CAssociation() { } HRESULT CAssociation::ExecQuery( MethodContext* pMethodContext, CFrameworkQuery &pQuery, long lFlags ) { HRESULT hr = WBEM_S_NO_ERROR; TRefPointerCollection lefts; CHStringArray sLeftPaths, sRightPaths; pQuery.GetValuesForProp ( m_pwszLeftPropertyName, sLeftPaths ) ; pQuery.GetValuesForProp ( m_pwszRightPropertyName, sRightPaths ) ; if (sLeftPaths.GetSize() == 0) { // GetLeftInstances populates lefts hr = GetLeftInstances(pMethodContext, lefts); } else { // For each sLeftPaths that is valid, create an entry in lefts hr = ValidateLeftObjectPaths(pMethodContext, sLeftPaths, lefts); } if (SUCCEEDED(hr) && lefts.GetSize() > 0) { if (sRightPaths.GetSize() == 0) { // GetRightInstances takes the 'lefts' and rubs all the // rights against them creating instances where appropriate hr = GetRightInstances(pMethodContext, &lefts); } else { TRefPointerCollection rights; // For each sRightPaths that is valid, create an instance hr = ValidateRightObjectPaths(pMethodContext, sRightPaths, lefts); } } return hr; } HRESULT CAssociation::GetObject( CInstance* pInstance, long lFlags, CFrameworkQuery &pQuery ) { HRESULT hr = WBEM_E_NOT_FOUND; CHString sLeftPath, sRightPath; // Get the two endpoints if (pInstance->GetCHString(m_pwszLeftPropertyName, sLeftPath ) && pInstance->GetCHString(m_pwszRightPropertyName, sRightPath ) ) { CInstancePtr pLeft, pRight; // Try to get the objects if (SUCCEEDED(hr = RetrieveLeftInstance(sLeftPath, &pLeft, pInstance->GetMethodContext())) && SUCCEEDED(hr = RetrieveRightInstance(sRightPath, &pRight, pInstance->GetMethodContext())) ) { hr = WBEM_E_NOT_FOUND; // So, the end points exist. Are they derived from or equal to the classes we are working with? CHString sLeftClass, sRightClass; pLeft->GetCHString(L"__CLASS", sLeftClass); pRight->GetCHString(L"__CLASS", sRightClass); BOOL bDerived = _wcsicmp(m_pwszLeftClassName, sLeftClass) == 0; if (!bDerived) { bDerived = CWbemProviderGlue::IsDerivedFrom(m_pwszLeftClassName, sLeftClass, pInstance->GetMethodContext()); } if (bDerived) { // Left side was correct, now let's check the right bDerived = _wcsicmp(m_pwszRightClassName, sRightClass) == 0; if (!bDerived) { bDerived = CWbemProviderGlue::IsDerivedFrom(m_pwszRightClassName, sRightClass, pInstance->GetMethodContext()); } } if (bDerived) { // Just because two instances are valid and derive from the right class, doesn't mean they are related. Do // any other checks. if (AreRelated(pLeft, pRight)) { hr = LoadPropertyValues(pInstance, pLeft, pRight); } } } } return hr; } HRESULT CAssociation::EnumerateInstances( MethodContext *pMethodContext, long lFlags /*= 0L*/ ) { HRESULT hr = WBEM_S_NO_ERROR; TRefPointerCollection lefts; // GetLeftInstances populates lefts if (SUCCEEDED(hr = GetLeftInstances(pMethodContext, lefts))) { // GetRightInstances takes the 'lefts' and rubs all the // rights against them hr = GetRightInstances(pMethodContext, &lefts); } return hr; } HRESULT CAssociation::GetRightInstances( MethodContext *pMethodContext, TRefPointerCollection *lefts ) { CHString sQuery; sQuery.Format(L"SELECT __RELPATH FROM %s", m_pwszRightClassName); // 'StaticEnumerationCallback' will get called once for each instance // returned from the query HRESULT hr = CWbemProviderGlue::GetInstancesByQueryAsynch( sQuery, this, StaticEnumerationCallback, NULL, pMethodContext, lefts); return hr; } HRESULT WINAPI CAssociation::StaticEnumerationCallback( Provider* pThat, CInstance* pInstance, MethodContext* pContext, void* pUserData ) { HRESULT hr; CAssociation *pThis = (CAssociation *) pThat; ASSERT_BREAK(pThis != NULL); if (pThis) { hr = pThis->EnumerationCallback(pInstance, pContext, pUserData); } else { hr = WBEM_S_NO_ERROR; } return hr; } HRESULT CAssociation::EnumerationCallback( CInstance *pRight, MethodContext *pMethodContext, void *pUserData ) { HRESULT hr = WBEM_E_FAILED; CInstancePtr pLeft; REFPTRCOLLECTION_POSITION posLeft; CHString sLeftPath, sRightPath; // Cast for userdata back to what it is TRefPointerCollection *pLefts = (TRefPointerCollection *)pUserData; if (pLefts->BeginEnum(posLeft)) { hr = WBEM_S_NO_ERROR; // Walk all the pLefts for (pLeft.Attach(pLefts->GetNext(posLeft)) ; (SUCCEEDED(hr)) && (pLeft != NULL) ; pLeft.Attach(pLefts->GetNext(posLeft)) ) { // Compare it to the current pRight if(AreRelated(pLeft, pRight)) { // We have a winner. Populate the properties and send it in. if (GetLocalInstancePath(pLeft, sLeftPath) && GetLocalInstancePath(pRight, sRightPath)) { CInstancePtr pNewAssoc(CreateNewInstance(pMethodContext), false); if (pNewAssoc->SetCHString(m_pwszLeftPropertyName, sLeftPath) && pNewAssoc->SetCHString(m_pwszRightPropertyName, sRightPath) ) { if (SUCCEEDED(hr = LoadPropertyValues(pNewAssoc, pLeft, pRight))) { hr = pNewAssoc->Commit(); } } else { ASSERT_BREAK(0); } } } } pLefts->EndEnum(); } return hr; } HRESULT CAssociation::ValidateLeftObjectPaths( MethodContext *pMethodContext, const CHStringArray &sPaths, TRefPointerCollection &lefts ) { CInstancePtr pInstance; // Walk the object paths for (DWORD x=0; x < sPaths.GetSize(); x++) { ParsedObjectPath *pParsedPath = NULL; CObjectPathParser objpathParser; int nStatus = objpathParser.Parse( sPaths[x], &pParsedPath ); if ( 0 == nStatus ) { BOOL bDerived; try { bDerived = _wcsicmp(m_pwszLeftClassName, pParsedPath->m_pClass) == 0; if (!bDerived) { bDerived = CWbemProviderGlue::IsDerivedFrom(m_pwszLeftClassName, pParsedPath->m_pClass, pMethodContext); } } catch ( ... ) { objpathParser.Free( pParsedPath ); throw; } objpathParser.Free( pParsedPath ); if (bDerived) { // See if it is valid if (SUCCEEDED(RetrieveLeftInstance(sPaths[x], &pInstance, pMethodContext))) { // Yup, add it to the list lefts.Add(pInstance); } } } } return WBEM_S_NO_ERROR; } HRESULT CAssociation::ValidateRightObjectPaths( MethodContext *pMethodContext, const CHStringArray &sPaths, TRefPointerCollection &lefts ) { HRESULT hr = WBEM_S_NO_ERROR;; CInstancePtr pInstance; // Walk the object paths for (DWORD x=0; (x < sPaths.GetSize()) && SUCCEEDED(hr); x++) { ParsedObjectPath *pParsedPath = NULL; CObjectPathParser objpathParser; int nStatus = objpathParser.Parse( sPaths[x], &pParsedPath ); if ( 0 == nStatus ) { BOOL bDerived; try { bDerived = _wcsicmp(m_pwszRightClassName, pParsedPath->m_pClass) == 0; if (!bDerived) { bDerived = CWbemProviderGlue::IsDerivedFrom(m_pwszRightClassName, pParsedPath->m_pClass, pMethodContext); } } catch ( ... ) { objpathParser.Free( pParsedPath ); throw; } objpathParser.Free( pParsedPath ); if (bDerived) { // See if it is valid if (SUCCEEDED(RetrieveRightInstance(sPaths[x], &pInstance, pMethodContext))) { hr = EnumerationCallback(pInstance, pMethodContext, &lefts); } } } } return hr; } HRESULT CAssociation::GetLeftInstances( MethodContext *pMethodContext, TRefPointerCollection &lefts ) { CHString sQuery; sQuery.Format(L"SELECT __RELPATH FROM %s", m_pwszLeftClassName); return CWbemProviderGlue::GetInstancesByQuery(sQuery, &lefts, pMethodContext); } HRESULT CAssociation::RetrieveLeftInstance( LPCWSTR lpwszObjPath, CInstance **ppInstance, MethodContext *pMethodContext ) { return CWbemProviderGlue::GetInstanceKeysByPath(lpwszObjPath, ppInstance, pMethodContext); } HRESULT CAssociation::RetrieveRightInstance( LPCWSTR lpwszObjPath, CInstance **ppInstance, MethodContext *pMethodContext ) { return CWbemProviderGlue::GetInstanceKeysByPath(lpwszObjPath, ppInstance, pMethodContext); } /* //======================== CAssocSystemToOS::CAssocSystemToOS( LPCWSTR pwszClassName, LPCWSTR pwszNamespaceName, LPCWSTR pwszLeftClassName, LPCWSTR pwszRightClassName, LPCWSTR pwszLeftPropertyName, LPCWSTR pwszRightPropertyName ) : CAssociation ( pwszClassName, pwszNamespaceName, pwszLeftClassName, pwszRightClassName, pwszLeftPropertyName, pwszRightPropertyName ) { } CAssocSystemToOS::~CAssocSystemToOS() { } HRESULT CAssocSystemToOS::LoadPropertyValues( CInstance *pInstance, const CInstance *pLeft, const CInstance *pRight ) { CAssociation::LoadPropertyValues(pInstance, pLeft, pRight); // This will work... until win32_os returns more than one instance. pInstance->Setbool(L"PrimaryOS", true); return WBEM_S_NO_ERROR; } CAssocSystemToOS MySystemToOperatingSystem( L"Win32_SystemOperatingSystem", L"root\\cimv2", L"Win32_ComputerSystem", L"Win32_OperatingSystem", IDS_GroupComponent, IDS_PartComponent ) ; */ bool CAssociation::IsInstance(const CInstance *pInstance) { DWORD dwGenus = 0; pInstance->GetDWORD(L"__Genus", dwGenus); return dwGenus == WBEM_GENUS_INSTANCE; }