477 lines
12 KiB
C++
477 lines
12 KiB
C++
//=================================================================
|
|
//
|
|
// assoc.cpp -- Generic association class
|
|
//
|
|
// Copyright 1999 Microsoft Corporation
|
|
//
|
|
//=================================================================
|
|
#include <stdafx.h>
|
|
#include "precomp.h"
|
|
#include <assertbreak.h>
|
|
|
|
#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<CInstance> 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<CInstance> 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<CInstance> 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<CInstance> *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<CInstance> *pLefts = (TRefPointerCollection<CInstance> *)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<CInstance> &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<CInstance> &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<CInstance> &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;
|
|
}
|