|
|
/*++
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)
|