You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
504 lines
11 KiB
504 lines
11 KiB
/*++
|
|
|
|
Copyright (C) 1996-2001 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
ASSRULE.CPP
|
|
|
|
Abstract:
|
|
|
|
History:
|
|
|
|
--*/
|
|
|
|
#include "assrule.h"
|
|
#include <stdio.h>
|
|
|
|
#define CLASSNAME_ASSOCIATION_RULE L"AssociationRule"
|
|
#define PROPNAME_ASSOCIATION_CLASS L"AssociationClass"
|
|
#define PROPNAME_RULE_IMMUTABLE L"RuleIsImmutable"
|
|
#define PROPNAME_PROPNAME_1 L"PropertyName1"
|
|
#define PROPNAME_QUERY_1 L"PropertyQuery1"
|
|
#define PROPNAME_IMMUTABLE_1 L"Property1IsImmutable"
|
|
#define PROPNAME_PROPNAME_2 L"PropertyName2"
|
|
#define PROPNAME_QUERY_2 L"PropertyQuery2"
|
|
#define PROPNAME_IMMUTABLE_2 L"Property2IsImmutable"
|
|
|
|
#define EXTRA_GET_PARAMS ,NULL, NULL
|
|
#define EXTRA_PUT_PARAMS ,0
|
|
|
|
CEndpointCache::CEndpointCache()
|
|
: m_strQuery(NULL), m_pEnum(NULL)
|
|
{
|
|
}
|
|
|
|
void CEndpointCache::Create(BSTR strQuery, BOOL bCache)
|
|
{
|
|
m_strQuery = SysAllocString(strQuery);
|
|
m_bCache = bCache;
|
|
}
|
|
|
|
CEndpointCache::~CEndpointCache()
|
|
{
|
|
SysFreeString(m_strQuery);
|
|
if(m_pEnum)
|
|
m_pEnum->Release();
|
|
}
|
|
|
|
|
|
HRESULT CEndpointCache::GetInstanceEnum(IWbemServices* pNamespace,
|
|
IEnumWbemClassObject** ppEnum)
|
|
{
|
|
if(m_pEnum)
|
|
{
|
|
*ppEnum = m_pEnum;
|
|
m_pEnum->AddRef();
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT hres = pNamespace->ExecQuery(L"WQL", m_strQuery, 0, ppEnum, NULL);
|
|
if(FAILED(hres)) return hres;
|
|
|
|
if(m_bCache)
|
|
{
|
|
m_pEnum = *ppEnum;
|
|
m_pEnum->AddRef();
|
|
}
|
|
|
|
return hres;
|
|
}
|
|
|
|
|
|
|
|
CAssocRule::CAssocRule()
|
|
: m_strAssocClass(NULL), m_strProp1(NULL), m_strProp2(NULL), m_pClass(NULL),
|
|
m_nRef(0), m_bMayCacheResult(FALSE), m_bResultCached(FALSE)
|
|
{
|
|
}
|
|
|
|
CAssocRule::~CAssocRule()
|
|
{
|
|
SysFreeString(m_strAssocClass);
|
|
SysFreeString(m_strProp1);
|
|
SysFreeString(m_strProp2);
|
|
|
|
if(m_pClass)
|
|
m_pClass->Release();
|
|
}
|
|
|
|
void CAssocRule::AddRef()
|
|
{
|
|
m_nRef++;
|
|
}
|
|
|
|
void CAssocRule::Release()
|
|
{
|
|
if(--m_nRef == 0)
|
|
{
|
|
delete this;
|
|
}
|
|
}
|
|
|
|
HRESULT CAssocRule::LoadFromObject(IWbemClassObject* pRule, BOOL bLongTerm)
|
|
{
|
|
HRESULT hres;
|
|
|
|
VARIANT v;
|
|
VariantInit(&v);
|
|
|
|
// Read association name
|
|
// =====================
|
|
|
|
hres = pRule->Get(PROPNAME_ASSOCIATION_CLASS, 0, &v EXTRA_GET_PARAMS);
|
|
if(FAILED(hres) || V_VT(&v) == VT_NULL)
|
|
{
|
|
return WBEM_E_FAILED;
|
|
}
|
|
m_strAssocClass = SysAllocString(V_BSTR(&v));
|
|
VariantClear(&v);
|
|
|
|
// Read property names
|
|
// ===================
|
|
|
|
hres = pRule->Get(PROPNAME_PROPNAME_1, 0, &v EXTRA_GET_PARAMS);
|
|
if(FAILED(hres) || V_VT(&v) == VT_NULL)
|
|
{
|
|
return WBEM_E_FAILED;
|
|
}
|
|
m_strProp1 = SysAllocString(V_BSTR(&v));
|
|
VariantClear(&v);
|
|
|
|
hres = pRule->Get(PROPNAME_PROPNAME_2, 0, &v EXTRA_GET_PARAMS);
|
|
if(FAILED(hres) || V_VT(&v) == VT_NULL)
|
|
{
|
|
return WBEM_E_FAILED;
|
|
}
|
|
m_strProp2 = SysAllocString(V_BSTR(&v));
|
|
VariantClear(&v);
|
|
|
|
m_bMayCacheResult = bLongTerm;
|
|
|
|
// Read property rule (1)
|
|
// ======================
|
|
|
|
VARIANT vImmutable;
|
|
VariantInit(&vImmutable);
|
|
|
|
hres = pRule->Get(PROPNAME_QUERY_1, 0, &v EXTRA_GET_PARAMS);
|
|
if(FAILED(hres) || V_VT(&v) == VT_NULL)
|
|
{
|
|
return WBEM_E_FAILED;
|
|
}
|
|
|
|
hres = pRule->Get(PROPNAME_IMMUTABLE_1, 0, &vImmutable EXTRA_GET_PARAMS);
|
|
if(FAILED(hres) || V_VT(&vImmutable) == VT_NULL)
|
|
{
|
|
return WBEM_E_FAILED;
|
|
}
|
|
|
|
m_Cache1.Create(V_BSTR(&v), V_BOOL(&vImmutable));
|
|
VariantClear(&v);
|
|
if(!V_BOOL(&vImmutable))
|
|
m_bMayCacheResult = FALSE;
|
|
|
|
// Read property rule (2)
|
|
// ======================
|
|
|
|
hres = pRule->Get(PROPNAME_QUERY_2, 0, &v EXTRA_GET_PARAMS);
|
|
if(FAILED(hres) || V_VT(&v) == VT_NULL)
|
|
{
|
|
return WBEM_E_FAILED;
|
|
}
|
|
|
|
hres = pRule->Get(PROPNAME_IMMUTABLE_2, 0, &vImmutable EXTRA_GET_PARAMS);
|
|
if(FAILED(hres) || V_VT(&vImmutable) == VT_NULL)
|
|
{
|
|
return WBEM_E_FAILED;
|
|
}
|
|
|
|
m_Cache2.Create(V_BSTR(&v), V_BOOL(&vImmutable));
|
|
VariantClear(&v);
|
|
if(!V_BOOL(&vImmutable))
|
|
m_bMayCacheResult = FALSE;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT CAssocRule::Produce(IWbemServices* pNamespace, IWbemObjectSink* pNotify)
|
|
{
|
|
HRESULT hres;
|
|
|
|
// Check if we have it cached
|
|
// ==========================
|
|
|
|
if(m_bResultCached)
|
|
{
|
|
return m_ObjectCache.Indicate(pNotify);
|
|
}
|
|
|
|
// Get first enumerator
|
|
// ====================
|
|
|
|
IEnumWbemClassObject* pEnum1;
|
|
hres = m_Cache1.GetInstanceEnum(pNamespace, &pEnum1);
|
|
if(FAILED(hres))
|
|
{
|
|
return hres;
|
|
}
|
|
|
|
// Get second enumerator
|
|
// =====================
|
|
|
|
IEnumWbemClassObject* pEnum2;
|
|
hres = m_Cache2.GetInstanceEnum(pNamespace, &pEnum2);
|
|
if(FAILED(hres))
|
|
{
|
|
pEnum1->Release();
|
|
return hres;
|
|
}
|
|
|
|
// Get the association class
|
|
// =========================
|
|
|
|
IWbemClassObject* pClass;
|
|
if(m_pClass != NULL)
|
|
{
|
|
pClass = m_pClass;
|
|
pClass->AddRef();
|
|
}
|
|
else
|
|
{
|
|
hres = pNamespace->GetObject(m_strAssocClass, 0, &pClass, NULL);
|
|
if(FAILED(hres))
|
|
{
|
|
pEnum1->Release();
|
|
pEnum2->Release();
|
|
return hres;
|
|
}
|
|
}
|
|
|
|
// Create all the associations
|
|
// ===========================
|
|
|
|
|
|
IWbemClassObject* pInstance1, *pInstance2;
|
|
ULONG lNum;
|
|
|
|
VARIANT v;
|
|
VariantInit(&v);
|
|
|
|
// Iterate through the first result set
|
|
// ====================================
|
|
|
|
pEnum1->Reset();
|
|
while(pEnum1->Next(1, &pInstance1, &lNum) == S_OK)
|
|
{
|
|
// Get the first path
|
|
// ==================
|
|
|
|
hres = pInstance1->Get(L"__PATH", 0, &v EXTRA_GET_PARAMS);
|
|
if(FAILED(hres))
|
|
{
|
|
pEnum1->Release();
|
|
pEnum2->Release();
|
|
pClass->Release();
|
|
return hres;
|
|
}
|
|
BSTR strPath1 = V_BSTR(&v);
|
|
VariantInit(&v); // intentional.
|
|
|
|
// Iterate through the second result set
|
|
// =====================================
|
|
|
|
pEnum2->Reset();
|
|
while(pEnum2->Next(1, &pInstance2, &lNum) == S_OK)
|
|
{
|
|
// Get the second path
|
|
// ===================
|
|
|
|
hres = pInstance2->Get(L"__PATH", 0, &v EXTRA_GET_PARAMS);
|
|
if(FAILED(hres))
|
|
{
|
|
pEnum1->Release();
|
|
pEnum2->Release();
|
|
pClass->Release();
|
|
return hres;
|
|
}
|
|
BSTR strPath2 = V_BSTR(&v);
|
|
VariantInit(&v); // intentional
|
|
|
|
// Create the association instance
|
|
// ===============================
|
|
|
|
IWbemClassObject* pInstance;
|
|
hres = pClass->SpawnInstance(0, &pInstance);
|
|
if(FAILED(hres))
|
|
{
|
|
pEnum1->Release();
|
|
pEnum2->Release();
|
|
pClass->Release();
|
|
return hres;
|
|
}
|
|
|
|
// Set the properties
|
|
// ==================
|
|
|
|
V_VT(&v) = VT_BSTR;
|
|
V_BSTR(&v) = strPath1;
|
|
|
|
hres = pInstance->Put(m_strProp1, 0, &v EXTRA_PUT_PARAMS);
|
|
if(FAILED(hres))
|
|
{
|
|
pEnum1->Release();
|
|
pEnum2->Release();
|
|
pClass->Release();
|
|
pInstance->Release();
|
|
return hres;
|
|
}
|
|
|
|
V_BSTR(&v) = strPath2;
|
|
hres = pInstance->Put(m_strProp2, 0, &v EXTRA_PUT_PARAMS);
|
|
if(FAILED(hres))
|
|
{
|
|
pEnum1->Release();
|
|
pEnum2->Release();
|
|
pClass->Release();
|
|
pInstance->Release();
|
|
return hres;
|
|
}
|
|
|
|
// Supply it
|
|
// =========
|
|
|
|
pNotify->Indicate(1, &pInstance);
|
|
|
|
// Cache it if allowed
|
|
// ===================
|
|
|
|
if(m_bMayCacheResult)
|
|
m_ObjectCache.Add(pInstance);
|
|
|
|
pInstance->Release();
|
|
|
|
SysFreeString(strPath2);
|
|
pInstance2->Release();
|
|
}
|
|
|
|
SysFreeString(strPath1);
|
|
pInstance1->Release();
|
|
}
|
|
|
|
pEnum1->Release();
|
|
pEnum2->Release();
|
|
pClass->Release();
|
|
|
|
if(m_bMayCacheResult)
|
|
m_bResultCached = TRUE;
|
|
return S_OK;
|
|
}
|
|
|
|
//*****************************************************************************
|
|
|
|
CAssocInfoCache::CAssocInfoCache() : m_pNamespace(NULL)
|
|
{
|
|
}
|
|
|
|
void CAssocInfoCache::SetNamespace(IWbemServices* pNamespace)
|
|
{
|
|
m_pNamespace = pNamespace;
|
|
m_pNamespace->AddRef();
|
|
}
|
|
|
|
CAssocInfoCache::~CAssocInfoCache()
|
|
{
|
|
if(m_pNamespace)
|
|
m_pNamespace->Release();
|
|
|
|
for(int i = 0; i < m_aRules.Size(); i++)
|
|
{
|
|
CAssocRule* pRule = (CAssocRule*)m_aRules[i];
|
|
pRule->Release();
|
|
}
|
|
}
|
|
|
|
|
|
HRESULT CAssocInfoCache::GetRuleForClass(BSTR strClass, CAssocRule** ppRule)
|
|
{
|
|
// Search our rules to see if we have it
|
|
// =====================================
|
|
|
|
for(int i = 0; i < m_aRules.Size(); i++)
|
|
{
|
|
CAssocRule* pRule = (CAssocRule*)m_aRules[i];
|
|
if(!wcsicmp(pRule->GetAssocClass(), strClass))
|
|
{
|
|
pRule->AddRef();
|
|
*ppRule = pRule;
|
|
return S_OK;
|
|
}
|
|
}
|
|
|
|
// Don't have it. Search for the rule in the database.
|
|
// ===================================================
|
|
|
|
HRESULT hres;
|
|
|
|
BSTR strPath = SysAllocStringLen(NULL, wcslen(strClass) + 100);
|
|
swprintf(strPath, L"%s.%s=\"%s\"", CLASSNAME_ASSOCIATION_RULE,
|
|
PROPNAME_ASSOCIATION_CLASS, strClass);
|
|
|
|
IWbemClassObject* pRuleInstance;
|
|
hres = m_pNamespace->GetObject(strPath, 0, &pRuleInstance, NULL);
|
|
SysFreeString(strPath);
|
|
if(FAILED(hres))
|
|
{
|
|
return hres;
|
|
}
|
|
|
|
// Check if it is cachable
|
|
// ========================
|
|
|
|
VARIANT v;
|
|
VariantInit(&v);
|
|
hres = pRuleInstance->Get(PROPNAME_RULE_IMMUTABLE, 0, &v EXTRA_GET_PARAMS);
|
|
if(FAILED(hres))
|
|
{
|
|
pRuleInstance->Release();
|
|
return hres;
|
|
}
|
|
|
|
// Got it. Create the rule.
|
|
// ========================
|
|
|
|
CAssocRule* pRule = new CAssocRule;
|
|
hres = pRule->LoadFromObject(pRuleInstance, V_BOOL(&v));
|
|
pRuleInstance->Release();
|
|
|
|
if(FAILED(hres))
|
|
{
|
|
delete pRule;
|
|
return hres;
|
|
}
|
|
|
|
// Cache if allowed
|
|
// ================
|
|
|
|
if(V_BOOL(&v))
|
|
{
|
|
m_aRules.Add(pRule);
|
|
pRule->AddRef();
|
|
}
|
|
|
|
// Return it to the caller
|
|
// =======================
|
|
|
|
pRule->AddRef();
|
|
*ppRule = pRule;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
|
|
|
|
//****************************************************************************
|
|
|
|
CObjectCache::~CObjectCache()
|
|
{
|
|
Invalidate();
|
|
}
|
|
|
|
void CObjectCache::Invalidate()
|
|
{
|
|
for(int i = 0; i < m_aObjects.Size(); i++)
|
|
{
|
|
IWbemClassObject* pObject = (IWbemClassObject*)m_aObjects[i];
|
|
pObject->Release();
|
|
}
|
|
m_aObjects.Empty();
|
|
}
|
|
|
|
void CObjectCache::Add(IWbemClassObject* pObject)
|
|
{
|
|
m_aObjects.Add((void*)pObject);
|
|
pObject->AddRef();
|
|
}
|
|
|
|
HRESULT CObjectCache::Indicate(IWbemObjectSink* pSink)
|
|
{
|
|
if(m_aObjects.Size() == 0)
|
|
return S_OK;
|
|
|
|
void** ppvData = m_aObjects.GetArrayPtr();
|
|
|
|
return pSink->Indicate(m_aObjects.Size(), (IWbemClassObject**)ppvData);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|