windows-nt/Source/XPSP1/NT/admin/wmi/wbem/winmgmt/esscli/twopropnode.cpp

773 lines
21 KiB
C++
Raw Permalink Normal View History

2020-09-26 03:20:57 -05:00
/*++
Copyright (C) 1996-1999 Microsoft Corporation
Module Name:
TWOPROPNODE.CPP
Abstract:
Two Prop Node
History:
--*/
// classes to support a two-property node for the eval tree
// this will be much like the CPropertyNode defined in EvalTree.h
// but it will compare a property against another property
// rather than a property to a constant
#include "precomp.h"
#include <stdio.h>
#pragma warning(disable:4786)
#include <wbemcomn.h>
#include <genutils.h>
#include "TwoPropNode.h"
// warning about performance hits when converting an int to a bool
#pragma warning(disable: 4800)
// this is only a test
// TTwoScalarPropNode<int> foolishMortal;
// set offset into object for the right property
// "tell me which property I'm operating on"
void CTwoPropNode::SetRightPropertyInfo(LPCWSTR wszPropName, long lPropHandle)
{
m_lRightPropHandle = lPropHandle;
}
void CTwoPropNode::SetRightEmbeddingInfo(const CEmbeddingInfo* pInfo)
{
try
{
if (pInfo && !pInfo->IsEmpty())
{
if (!m_pRightInfo)
m_pRightInfo = new CEmbeddingInfo(*pInfo);
else
*m_pRightInfo = *pInfo;
}
else
{
delete m_pRightInfo;
m_pRightInfo = NULL;
}
}
catch(CX_MemoryException)
{
}
}
HRESULT CTwoPropNode::GetRightContainerObject(CObjectInfo& ObjInfo,
INTERNAL _IWmiObject** ppInst)
{
if (!m_pRightInfo)
{
*ppInst = ObjInfo.GetObjectAt(0);
return WBEM_S_NO_ERROR;
}
else
return m_pRightInfo->GetContainerObject(ObjInfo, ppInst);
}
HRESULT CTwoPropNode::CompileRightEmbeddingPortion(CContextMetaData* pNamespace,
CImplicationList& Implications,
_IWmiObject** ppResultClass)
{
if (!m_pRightInfo)
return WBEM_E_FAILED;
else
return m_pRightInfo->Compile(pNamespace, Implications, ppResultClass);
}
void CTwoPropNode::SetRightEmbeddedObjPropName(CPropertyName& Name)
{
if (m_pRightInfo)
m_pRightInfo->SetEmbeddedObjPropName(Name);
}
void CTwoPropNode::MixInJumpsRightObj(const CEmbeddingInfo* pParent)
{
if (pParent && m_pRightInfo)
m_pRightInfo->MixInJumps(pParent);
}
CPropertyName* CTwoPropNode::GetRightEmbeddedObjPropName()
{
if (!m_pRightInfo)
return NULL;
else
return m_pRightInfo->GetEmbeddedObjPropName();
}
// compare precedence of this node to that node
int CTwoPropNode::ComparePrecedence(CBranchingNode* pOther)
{
int nCompare;
nCompare = GetSubType() - pOther->GetSubType();
if(nCompare) return nCompare;
CTwoPropNode* pOtherNode = (CTwoPropNode*)pOther;
nCompare = m_pRightInfo->ComparePrecedence(pOtherNode->m_pRightInfo);
if (nCompare == 0)
{
nCompare = CPropertyNode::ComparePrecedence(pOther);
if (nCompare == 0)
nCompare = m_lRightPropHandle - pOtherNode->m_lRightPropHandle;
}
return nCompare;
}
HRESULT CTwoPropNode::AdjustCompile(CContextMetaData* pNamespace,
CImplicationList& Implications)
{
HRESULT hRes;
if (SUCCEEDED(hRes = CBranchingNode::AdjustCompile(pNamespace, Implications)))
if (m_pRightInfo)
hRes = m_pRightInfo->Compile(pNamespace, Implications, NULL);
else
hRes = WBEM_E_FAILED;
return hRes;
}
HRESULT CTwoPropNode::OptimizeSelf()
{
// can't combine our three branches - nothing to do.
return WBEM_S_NO_ERROR;
}
HRESULT CTwoPropNode::SetTest(VARIANT& v)
{
// again, nothing to do, our test is determined by the Right side property
// (this should never be called, but doesn't hurt anything)
return WBEM_S_NO_ERROR;
}
void CTwoPropNode::Dump(FILE* f, int nOffset)
{
PrintOffset(f, nOffset);
if (m_pInfo)
m_pInfo->Dump(f);
if (m_pRightInfo)
m_pRightInfo->Dump(f);
fprintf(f, ", LeftPropHandle = (0x%x)\n", m_lPropHandle);
fprintf(f, ", RightPropHandle = (0x%x)\n", m_lRightPropHandle);
fprintf(f, "Branches:\n");
PrintOffset(f, nOffset);
// "i = (Operations)((int)(i) + 1)" is basically i++, with all the BS needed to make the compiler happy.
// thank you K&R for saddling us with a nearly useless enum type!
for (Operations i = LT; i < NOperations; i = (Operations)((int)(i) + 1))
{
DumpNode(f, nOffset+1, m_apBranches[i]);
fprintf(f, "\n");
}
fprintf(f, "NULL->\n");
DumpNode(f, nOffset+1, m_pNullBranch);
}
int CTwoPropNode::SubCompare(CEvalNode* pRawOther)
{
CTwoPropNode* pOther =
(CTwoPropNode*)pRawOther;
int nCompare;
nCompare = m_lPropHandle - pOther->m_lPropHandle;
if(nCompare)
return nCompare;
nCompare = m_lRightPropHandle - pOther->m_lRightPropHandle;
if(nCompare)
return nCompare;
nCompare = m_apBranches.GetSize() - pOther->m_apBranches.GetSize();
if(nCompare)
return nCompare;
return TRUE;
}
HRESULT CTwoPropNode::CombineBranchesWith(CBranchingNode* pArg2, int nOp,
CContextMetaData* pNamespace,
CImplicationList& Implications,
bool bDeleteThis, bool bDeleteArg2,
CEvalNode** ppRes)
{
// step one, determine whether we can reuse a node
CTwoPropNode* pNewNode = NULL;
CTwoPropNode* pDeleteMe = NULL;
if (bDeleteThis && bDeleteArg2)
{
pNewNode = this;
pDeleteMe = (CTwoPropNode*) pArg2;
}
else if (bDeleteThis)
pNewNode = this;
else if (bDeleteArg2)
pNewNode = (CTwoPropNode*) pArg2;
else
pNewNode = CloneSelfWithoutChildren();
HRESULT hRes = WBEM_S_NO_ERROR;
CTwoPropNode* pOther = (CTwoPropNode*)pArg2;
for (int i = LT; i < NOperations && SUCCEEDED(hRes); i++)
{
CEvalNode* pNewChildNode = NULL;
hRes = CEvalTree::Combine(m_apBranches[i], pOther->m_apBranches[i],
nOp, pNamespace, Implications, bDeleteThis, bDeleteArg2, &pNewChildNode);
if (bDeleteArg2)
pOther->m_apBranches.Discard(i);
if (bDeleteThis)
m_apBranches.Discard(i);
pNewNode->m_apBranches.Discard(i);
pNewNode->m_apBranches.SetAt(i, pNewChildNode);
}
if(pDeleteMe)
{
pDeleteMe->m_pNullBranch = NULL;
delete pDeleteMe;
}
if (SUCCEEDED(hRes))
*ppRes = pNewNode;
else
{
*ppRes = NULL;
}
return hRes;
}
// given a property handle, will retrieve proper property, probably.
CVar* CTwoPropNode::GetPropVariant(_IWmiObject* pObj, long lHandle, CIMTYPE* pct)
{
CVar *pVar = NULL;
BSTR bstrName;
if (SUCCEEDED(pObj->GetPropertyInfoByHandle(lHandle, &bstrName, pct)))
{
CSysFreeMe sfm(bstrName);
//
// Get it into a VARIANT
//
VARIANT v;
if(FAILED(pObj->Get(bstrName, 0, &v, NULL, NULL)))
return NULL;
// Convert it to a CVar
if (pVar = new CVar)
pVar->SetVariant(&v);
}
return pVar;
}
// ***************************
// **** Two String Prop Node ****
// ***************************
CEvalNode* CTwoStringPropNode::Clone() const
{
return (CEvalNode *) new CTwoStringPropNode(*this, true);
}
CTwoPropNode* CTwoStringPropNode::CloneSelfWithoutChildren() const
{
return (CTwoPropNode *) new CTwoStringPropNode(*this, false);
}
long CTwoStringPropNode::GetSubType()
{
return EVAL_NODE_TYPE_TWO_STRINGS;
}
HRESULT CTwoStringPropNode::Evaluate(CObjectInfo& ObjInfo,
INTERNAL CEvalNode** ppNext)
{
HRESULT herslut = WBEM_S_NO_ERROR;
_IWmiObject* pLeftObj;
_IWmiObject* pRightObj;
if(SUCCEEDED(herslut = GetContainerObject(ObjInfo, &pLeftObj))
&&
SUCCEEDED(herslut = GetRightContainerObject(ObjInfo, &pRightObj)))
{
CCompressedString* pLeftStr;
CCompressedString* pRightStr;
pLeftStr = CoreGetPropertyString(pLeftObj, m_lPropHandle);
pRightStr = CoreGetPropertyString(pRightObj, m_lRightPropHandle);
if ((pLeftStr == NULL) || (pRightStr == NULL))
{
*ppNext = m_pNullBranch;
herslut = WBEM_S_NO_ERROR;
}
else
{
int nCompare = pLeftStr->CheapCompare(*pRightStr);
// TODO: check to see if CheapCompare is guaranteed to return -1,0,1
// if so, then the multiple else if becomes
// *ppNext = m_apBranches[EQ + nCompare];
if (nCompare < 0)
*ppNext = m_apBranches[LT];
else if (nCompare > 0)
*ppNext = m_apBranches[GT];
else
*ppNext = m_apBranches[EQ];
herslut = WBEM_S_NO_ERROR;
}
}
return herslut;
}
// *******************************
// **** Two Mismatched Prop Node ****
// *******************************
HRESULT CTwoMismatchedPropNode::Evaluate(CObjectInfo& ObjInfo, INTERNAL CEvalNode** ppNext)
{
CVar *pLeftVar = NULL;
CVar *pRightVar = NULL;
HRESULT hr = WBEM_E_FAILED; // guilty until proven innocent
CIMTYPE ct;
_IWmiObject* pLeftObj = NULL;
_IWmiObject* pRightObj = NULL;
// if we can get the objects and variants...
if ((SUCCEEDED(hr = GetContainerObject(ObjInfo, &pLeftObj))
&&
SUCCEEDED(hr = GetRightContainerObject(ObjInfo, &pRightObj)))
&&
(pLeftVar = GetPropVariant(pLeftObj, m_lPropHandle, &ct))
&&
(pRightVar = GetPropVariant(pRightObj, m_lRightPropHandle, &ct)) )
{
if (pLeftVar->IsDataNull() || pRightVar->IsDataNull())
{
*ppNext = m_pNullBranch;
hr = WBEM_S_NO_ERROR;
}
else
hr = Evaluate(pLeftVar, pRightVar, ppNext);
}
else if (SUCCEEDED(hr))
// if we got here, it's because one of the GetPropVariant's didn't
hr = WBEM_E_INVALID_PARAMETER;
delete pLeftVar;
delete pRightVar;
return hr;
}
// **************************************
// **** Two Mismatched String Prop Node ****
// **************************************
CEvalNode* CTwoMismatchedStringNode::Clone() const
{
return (CEvalNode *) new CTwoMismatchedStringNode(*this, true);
}
CTwoPropNode* CTwoMismatchedStringNode::CloneSelfWithoutChildren() const
{
return (CTwoPropNode *) new CTwoMismatchedStringNode(*this, false);
}
// type identification
long CTwoMismatchedStringNode::GetSubType()
{
return EVAL_NODE_TYPE_MISMATCHED_STRINGS;
}
// string evaluation: promote them all to strings
// and do a lexagraphic compare..
HRESULT CTwoMismatchedStringNode::Evaluate(CVar *pLeftVar, CVar *pRightVar, INTERNAL CEvalNode** ppNext)
{
HRESULT hr = WBEM_E_FAILED; // guilty until proven innocent
if (pLeftVar->ChangeTypeTo(VT_BSTR) && pRightVar->ChangeTypeTo(VT_BSTR))
{
int nCompare = wcscmp(pLeftVar->GetLPWSTR(), pRightVar->GetLPWSTR());
if (nCompare < 0)
*ppNext = m_apBranches[LT];
else if (nCompare > 0)
*ppNext = m_apBranches[GT];
else
*ppNext = m_apBranches[EQ];
hr = WBEM_S_NO_ERROR;
}
else
hr = WBEM_E_FAILED;
return hr;
}
// ************************************
// **** Two Mismatched UINT Prop Node ****
// ************************************
CEvalNode* CTwoMismatchedUIntNode::Clone() const
{
return (CEvalNode *) new CTwoMismatchedUIntNode(*this, true);
}
CTwoPropNode* CTwoMismatchedUIntNode::CloneSelfWithoutChildren() const
{
return (CTwoPropNode *) new CTwoMismatchedUIntNode(*this, false);
}
// type identification
long CTwoMismatchedUIntNode::GetSubType()
{
return EVAL_NODE_TYPE_MISMATCHED_INTS;
}
HRESULT CTwoMismatchedUIntNode::Evaluate(CVar *pLeftVar, CVar *pRightVar, INTERNAL CEvalNode** ppNext)
{
HRESULT hr = WBEM_E_FAILED; // guilty until proven innocent
bool bLeftChanged, bRightChanged;
bLeftChanged = pLeftVar->ChangeTypeTo(VT_UI4);
bRightChanged = pRightVar->ChangeTypeTo(VT_UI4);
if (bLeftChanged && bRightChanged)
{
if (pLeftVar->GetDWORD() < pRightVar->GetDWORD())
*ppNext = m_apBranches[LT];
else if (pLeftVar->GetDWORD() > pRightVar->GetDWORD())
*ppNext = m_apBranches[GT];
else
*ppNext = m_apBranches[EQ];
hr = WBEM_S_NO_ERROR;
}
// attempt to handle signed/unsigned mismatches
else if (bLeftChanged &&
pRightVar->ChangeTypeTo(VT_I4) &&
pRightVar->GetLong() < 0)
{
*ppNext = m_apBranches[GT];
hr = WBEM_S_NO_ERROR;
}
else if (bRightChanged &&
pLeftVar->ChangeTypeTo(VT_I4) &&
pLeftVar->GetLong() < 0)
{
*ppNext = m_apBranches[LT];
hr = WBEM_S_NO_ERROR;
}
else
hr = WBEM_E_TYPE_MISMATCH;
return hr;
}
// ***********************************
// **** Two Mismatched int Prop Node ****
// ***********************************
CEvalNode* CTwoMismatchedIntNode::Clone() const
{
return (CEvalNode *) new CTwoMismatchedIntNode(*this, true);
}
CTwoPropNode* CTwoMismatchedIntNode::CloneSelfWithoutChildren() const
{
return (CTwoPropNode *) new CTwoMismatchedIntNode(*this, false);
}
// type identification
long CTwoMismatchedIntNode::GetSubType()
{
return EVAL_NODE_TYPE_MISMATCHED_INTS;
}
HRESULT CTwoMismatchedIntNode::Evaluate(CVar *pLeftVar, CVar *pRightVar, INTERNAL CEvalNode** ppNext)
{
HRESULT hr = WBEM_E_FAILED; // guilty until proven innocent
bool bLeftChanged, bRightChanged;
bLeftChanged = pLeftVar->ChangeTypeTo(VT_I4);
bRightChanged = pRightVar->ChangeTypeTo(VT_I4);
if (bLeftChanged && bRightChanged)
{
if (pLeftVar->GetLong() < pRightVar->GetLong())
*ppNext = m_apBranches[LT];
else if (pLeftVar->GetLong() > pRightVar->GetLong())
*ppNext = m_apBranches[GT];
else
*ppNext = m_apBranches[EQ];
hr = WBEM_S_NO_ERROR;
}
// attempt to handle signed/unsigned mismatches
else if (bLeftChanged &&
pRightVar->ChangeTypeTo(VT_UI4) &&
pRightVar->GetDWORD() > _I32_MAX)
{
*ppNext = m_apBranches[LT];
hr = WBEM_S_NO_ERROR;
}
else if (bRightChanged &&
pLeftVar->ChangeTypeTo(VT_UI4) &&
pLeftVar->GetDWORD() > _I32_MAX)
{
*ppNext = m_apBranches[GT];
hr = WBEM_S_NO_ERROR;
}
else
hr = WBEM_E_TYPE_MISMATCH;
return hr;
}
// **************************************
// **** Two Mismatched int 64 Prop Node ****
// **************************************
CEvalNode* CTwoMismatchedInt64Node::Clone() const
{
return (CEvalNode *) new CTwoMismatchedInt64Node(*this, true);
}
CTwoPropNode* CTwoMismatchedInt64Node::CloneSelfWithoutChildren() const
{
return (CTwoPropNode *) new CTwoMismatchedInt64Node(*this, false);
}
// type identification
long CTwoMismatchedInt64Node::GetSubType()
{
return EVAL_NODE_TYPE_MISMATCHED_INTS;
}
HRESULT CTwoMismatchedInt64Node::Evaluate(CVar *pLeftVar, CVar *pRightVar, INTERNAL CEvalNode** ppNext)
{
HRESULT hr = WBEM_E_FAILED; // guilty until proven innocent
__int64 i64Left, i64Right;
unsigned __int64 ui64;
if (pLeftVar->ChangeTypeTo(VT_BSTR) &&
pRightVar->ChangeTypeTo(VT_BSTR))
{
if ((pLeftVar->GetLPWSTR() == NULL) || (pRightVar->GetLPWSTR() == NULL))
*ppNext = m_pNullBranch;
else
{
bool bReadLeft, bReadRight;
bReadLeft = ReadI64(pLeftVar->GetLPWSTR(), i64Left);
bReadRight = ReadI64(pRightVar->GetLPWSTR(), i64Right);
if (bReadLeft && bReadRight)
{
if (i64Left < i64Right)
*ppNext = m_apBranches[LT];
else if (i64Left > i64Right)
*ppNext = m_apBranches[GT];
else
*ppNext = m_apBranches[EQ];
hr = WBEM_S_NO_ERROR;
}
// try to cover ourselves with signed/unsigned mismatches
// note that this is a redundant check - if the other side
// were a unsigned int 64, this node should have been a UInt64 node.
else if (bReadLeft &&
ReadUI64(pRightVar->GetLPWSTR(), ui64)
&& (ui64 >= _I64_MAX))
{
*ppNext = m_apBranches[LT];
hr = WBEM_S_NO_ERROR;
}
else if (bReadRight &&
ReadUI64(pLeftVar->GetLPWSTR(), ui64)
&& (ui64 >= _I64_MAX))
{
*ppNext = m_apBranches[GT];
hr = WBEM_S_NO_ERROR;
}
else
hr = WBEM_E_TYPE_MISMATCH;
} // if ((pLeftVar->GetLPWSTR() == NULL)...
} // if (pLeftVar->ChangeTypeTo(VT_BSTR)
else
hr = WBEM_E_TYPE_MISMATCH;
return hr;
}
// ***********************************************
// **** Two Mismatched unsigned int 64 Prop Node ****
// ***********************************************
CEvalNode* CTwoMismatchedUInt64Node::Clone() const
{
return (CEvalNode *) new CTwoMismatchedUInt64Node(*this, true);
}
CTwoPropNode* CTwoMismatchedUInt64Node::CloneSelfWithoutChildren() const
{
return (CTwoPropNode *) new CTwoMismatchedUInt64Node(*this, false);
}
// type identification
long CTwoMismatchedUInt64Node::GetSubType()
{
return EVAL_NODE_TYPE_MISMATCHED_INTS;
}
HRESULT CTwoMismatchedUInt64Node::Evaluate(CVar *pLeftVar, CVar *pRightVar, INTERNAL CEvalNode** ppNext)
{
HRESULT hr = WBEM_E_FAILED; // guilty until proven innocent
unsigned __int64 i64Left, i64Right;
__int64 i64;
if (pLeftVar->ChangeTypeTo(VT_BSTR) &&
pRightVar->ChangeTypeTo(VT_BSTR))
{
if ((pLeftVar->GetLPWSTR() == NULL) || (pRightVar->GetLPWSTR() == NULL))
*ppNext = m_pNullBranch;
else
{
bool bReadLeft, bReadRight;
bReadLeft = ReadUI64(pLeftVar->GetLPWSTR(), i64Left);
bReadRight = ReadUI64(pRightVar->GetLPWSTR(), i64Right);
if (bReadLeft && bReadRight)
{
if (i64Left < i64Right)
*ppNext = m_apBranches[LT];
else if (i64Left > i64Right)
*ppNext = m_apBranches[GT];
else
*ppNext = m_apBranches[EQ];
hr = WBEM_S_NO_ERROR;
}
// try to cover ourselves with signed/unsigned mismatches
else if (bReadLeft &&
ReadI64(pRightVar->GetLPWSTR(), i64)
&& (i64 < 0))
{
*ppNext = m_apBranches[GT];
hr = WBEM_S_NO_ERROR;
}
else if (bReadRight &&
ReadI64(pLeftVar->GetLPWSTR(), i64)
&& (i64 < 0))
{
*ppNext = m_apBranches[LT];
hr = WBEM_S_NO_ERROR;
}
else
hr = WBEM_E_TYPE_MISMATCH;
}
}
else
hr = WBEM_E_TYPE_MISMATCH;
return hr;
}
// *************************************
// **** Two Mismatched Float Prop Node ****
// *************************************
CEvalNode* CTwoMismatchedFloatNode::Clone() const
{
return (CEvalNode *) new CTwoMismatchedFloatNode(*this, true);
}
CTwoPropNode* CTwoMismatchedFloatNode::CloneSelfWithoutChildren() const
{
return (CTwoPropNode *) new CTwoMismatchedFloatNode(*this, false);
}
// type identification
long CTwoMismatchedFloatNode::GetSubType()
{
return EVAL_NODE_TYPE_MISMATCHED_FLOATS;
}
HRESULT CTwoMismatchedFloatNode::Evaluate(CVar *pLeftVar, CVar *pRightVar, INTERNAL CEvalNode** ppNext)
{
HRESULT hr = WBEM_E_TYPE_MISMATCH; // guilty until proven innocent
if (pLeftVar->ChangeTypeTo(VT_R8) && pRightVar->ChangeTypeTo(VT_R8))
{
if (pLeftVar->GetDouble() < pRightVar->GetDouble())
*ppNext = m_apBranches[LT];
else if (pLeftVar->GetDouble() > pRightVar->GetDouble())
*ppNext = m_apBranches[GT];
else
*ppNext = m_apBranches[EQ];
hr = WBEM_S_NO_ERROR;
}
return hr;
}
#pragma warning(default: 4800)