windows-nt/Source/XPSP1/NT/admin/wmi/wbem/providers/viewprovider/vptasksj.cpp
2020-09-26 16:20:57 +08:00

1271 lines
30 KiB
C++

//***************************************************************************
//
// VPTASKSJ.CPP
//
// Module: WBEM VIEW PROVIDER
//
// Purpose: Contains the join methods for taskobject implementation
//
// Copyright (c) 1998-2001 Microsoft Corporation, All Rights Reserved
//
//***************************************************************************
#include "precomp.h"
#include <provexpt.h>
#include <provcoll.h>
#include <provtempl.h>
#include <provmt.h>
#include <typeinfo.h>
#include <process.h>
#include <objbase.h>
#include <objidl.h>
#include <stdio.h>
#include <wbemidl.h>
#include <provcont.h>
#include <provevt.h>
#include <provthrd.h>
#include <provlog.h>
#include <cominit.h>
#include <dsgetdc.h>
#include <lmcons.h>
#include <lmapibuf.h>
#include <instpath.h>
#include <genlex.h>
#include <sql_1.h>
#include <objpath.h>
#include <vpdefs.h>
#include <vpcfac.h>
#include <vpquals.h>
#include <vpserv.h>
#include <vptasks.h>
#include <wbemtime.h>
BOOL CompareSimplePropertyValues(VARIANT* v1, VARIANT* v2, CIMTYPE ct)
{
BOOL retVal = FALSE;
if (v1->vt == v2->vt)
{
switch (ct)
{
case CIM_BOOLEAN:
{
if (VT_BOOL == v1->vt)
{
if (v1->boolVal == v2->boolVal)
{
retVal = TRUE;
}
}
}
break;
case CIM_UINT8:
{
if (VT_UI1 == v1->vt)
{
if (v1->bVal == v2->bVal)
{
retVal = TRUE;
}
}
}
break;
case CIM_SINT16:
case CIM_CHAR16:
case CIM_SINT8:
{
if (VT_I2 == v1->vt)
{
if (v1->iVal == v2->iVal)
{
retVal = TRUE;
}
}
}
break;
case CIM_UINT32:
case CIM_SINT32:
case CIM_UINT16:
{
if (VT_I4 == v1->vt)
{
if (v1->lVal == v2->lVal)
{
retVal = TRUE;
}
}
}
break;
case CIM_REFERENCE:
//TO DO:
//references should be normalised for equality checks.
//should do this once CIMOM does...
case CIM_STRING:
case CIM_SINT64:
case CIM_UINT64:
{
if (VT_BSTR == v1->vt)
{
if (0 == _wcsicmp(v1->bstrVal,v2->bstrVal))
{
retVal = TRUE;
}
}
}
break;
case CIM_DATETIME:
{
if (VT_BSTR == v1->vt)
{
WBEMTime t1(v1->bstrVal);
WBEMTime t2(v2->bstrVal);
if (t1 == t2)
{
retVal = TRUE;
}
}
}
break;
default:
{
//unsupported by this function
}
}
}
return retVal;
}
//Validate:
//1) All classes mentioned in join exist.
//2) All properties mentioned in join map to view class properties
//3) All classes mentioned in sources are mentioned in join
//4) Any != operator is not applied to two properties which map to the same view property
//5) All clauses have different classes being checked
BOOL WbemTaskObject::ValidateJoin()
{
//3) check all sources mentioned in join
//this check with (1) will do the trick
if (m_JoinOnArray.m_AllClasses.GetCount() != m_SourceArray.GetSize())
{
return FALSE;
}
//1) check all join classes exist
POSITION pos = m_JoinOnArray.m_AllClasses.GetStartPosition();
while (pos)
{
int val;
CStringW tmpStr;
m_JoinOnArray.m_AllClasses.GetNextAssoc(pos, tmpStr, val);
if (!m_ClassToIndexMap.Lookup(tmpStr, val))
{
return FALSE;
}
}
wchar_t** classA = m_JoinOnArray.GetAClasses();
wchar_t** propsA = m_JoinOnArray.GetAProperties();
wchar_t** classB = m_JoinOnArray.GetBClasses();
wchar_t** propsB = m_JoinOnArray.GetBProperties();
UINT* ops = m_JoinOnArray.GetOperators();
//(2), (4) and (5) validations
//=============================
for (int x = 0; x < m_JoinOnArray.GetCount(); x++)
{
if (_wcsicmp(classA[x], classB[x]) == 0)
{
return FALSE;
}
int indexA;
if (m_ClassToIndexMap.Lookup(classA[x], indexA))
{
int indexB;
if (m_ClassToIndexMap.Lookup(classB[x], indexB))
{
POSITION pos = m_PropertyMap.GetStartPosition();
CStringW propA;
CStringW propB;
while (pos)
{
CStringW key;
CPropertyQualifierItem* pItem;
m_PropertyMap.GetNextAssoc(pos, key, pItem);
if (pItem->m_SrcPropertyNames[indexA].CompareNoCase(propsA[x]) == 0)
{
propA = key;
if (!propB.IsEmpty())
{
break;
}
}
if (pItem->m_SrcPropertyNames[indexB].CompareNoCase(propsB[x]) == 0)
{
propB = key;
if (!propA.IsEmpty())
{
break;
}
}
}
//check both properties exist (2)
if (propA.IsEmpty() || propB.IsEmpty())
{
return FALSE;
}
//validate expression (4)
if (ops[x] == CJoinOnQualifierArray::NOT_EQUALS_OPERATOR && (propA.CompareNoCase(propB) == 0))
{
return FALSE;
}
}
else
{
return FALSE;
}
}
else
{
return FALSE;
}
}
return TRUE;
}
#ifdef VP_PERFORMANT_JOINS
//should not compile with compiler flag set til I'm ready
BOOL WbemTaskObject::CreateAndIndicateJoinsPerf(WbemProvErrorObject &a_ErrorObject, BOOL a_bSingle)
{
BOOL retVal = TRUE;
//check all queries were asked...
if (m_ObjSinkArray.GetSize() != m_SourceArray.GetSize())
{
retVal = FALSE;
a_ErrorObject.SetStatus ( WBEM_PROV_E_UNEXPECTED ) ;
a_ErrorObject.SetWbemStatus ( WBEM_E_FAILED ) ;
a_ErrorObject.SetMessage ( L"A source query failed or was not executed therefore a join could not be created." );
}
//check we got results from all queries...
for (UINT x = 0; x < m_ObjSinkArray.GetSize(); x++)
{
if ((m_ObjSinkArray[x] == NULL) || FAILED(m_ObjSinkArray[x]->GetResult()) || !m_ObjSinkArray[x]->m_ObjArray.GetSize())
{
if (!a_bSingle)
{
a_ErrorObject.SetStatus ( WBEM_PROV_E_UNEXPECTED ) ;
a_ErrorObject.SetWbemStatus ( WBEM_E_FAILED ) ;
a_ErrorObject.SetMessage ( L"A source query failed or returned no instances." );
}
retVal = FALSE;
break;
}
}
//perform the join of all results...
if (retVal)
{
CMap<CStringW, LPCWSTR, int, int> t_JoinedClasses;
CList<IWbemClassObject*, IWbemClassObject*> t_ResultObjs;
retVal = JoinTwoColumns(a_ErrorObject, t_JoinedClasses, t_ResultObjs);
wchar_t** t_clsA = m_JoinOnArray.GetAClasses();
wchar_t** t_clsB = m_JoinOnArray.GetBClasses();
wchar_t** t_prpsA = m_JoinOnArray.GetAProperties();
wchar_t** t_prpsB = m_JoinOnArray.GetBProperties();
while ( retVal && (t_JoinedClasses.GetCount() != m_SourceArray.GetSize()) )
{
DWORD t_column = m_SourceArray.GetSize() + 1;
CList <int, int> t_IndexArray;
wchar_t *t_classname = NULL;
//find a column not already joined that can be joined now...
for (x = 0; x < m_JoinOnArray.GetCount(); x++)
{
if (!m_JoinOnArray.m_bDone[x])
{
int dummyInt = 0;
if (t_classname == NULL)
{
if (t_JoinedClasses.Lookup(t_clsA[x], dummyInt))
{
if (!m_ClassToIndexMap.Lookup(t_clsB[x], (int &)t_column))
{
retVal = FALSE;
a_ErrorObject.SetStatus ( WBEM_PROV_E_UNEXPECTED ) ;
a_ErrorObject.SetWbemStatus ( WBEM_E_FAILED ) ;
a_ErrorObject.SetMessage ( L"An unexpected error ocurred performing the join." );
}
t_classname = t_clsB[x];
t_JoinedClasses.SetAt(t_classname, 0);
m_JoinOnArray.m_bDone[x] = TRUE;
t_IndexArray.AddTail(x);
//want all clauses the same way around...
t_clsB[x] = t_clsA[x];
t_clsA[x] = t_classname;
wchar_t *t_tmpStr = t_prpsA[x];
t_prpsA[x] = t_prpsB[x];
t_prpsB[x] = t_tmpStr;
}
else if (t_JoinedClasses.Lookup(t_clsB[x], dummyInt))
{
if (!m_ClassToIndexMap.Lookup(t_clsA[x], (int &)t_column))
{
retVal = FALSE;
a_ErrorObject.SetStatus ( WBEM_PROV_E_UNEXPECTED ) ;
a_ErrorObject.SetWbemStatus ( WBEM_E_FAILED ) ;
a_ErrorObject.SetMessage ( L"An unexpected error ocurred performing the join." );
}
t_classname = t_clsA[x];
t_JoinedClasses.SetAt(t_classname, 0);
m_JoinOnArray.m_bDone[x] = TRUE;
t_IndexArray.AddTail(x);
}
}
else
{
//find all clauses which can be evaluated now...
if ((_wcsicmp(t_classname, t_clsA[x]) == 0) && (t_JoinedClasses.Lookup(t_clsB[x], dummyInt)))
{
t_IndexArray.AddTail(x);
m_JoinOnArray.m_bDone[x] = TRUE;
}
else if ((_wcsicmp(t_classname, t_clsB[x]) == 0) && (t_JoinedClasses.Lookup(t_clsA[x], dummyInt)))
{
//want the clauses in the same order for simpler evaluation later...
wchar_t *t_tmpStr = t_clsA[x];
t_clsA[x] = t_clsB[x];
t_clsB[x] = t_tmpStr;
t_tmpStr = t_prpsA[x];
t_prpsA[x] = t_prpsB[x];
t_prpsB[x] = t_tmpStr;
t_IndexArray.AddTail(x);
m_JoinOnArray.m_bDone[x] = TRUE;
}
}
}
}
if (t_column == m_SourceArray.GetSize() + 1)
{
retVal = FALSE;
a_ErrorObject.SetStatus ( WBEM_PROV_E_UNEXPECTED ) ;
a_ErrorObject.SetWbemStatus ( WBEM_E_FAILED ) ;
a_ErrorObject.SetMessage ( L"Failed to perform join." );
}
else
{
retVal = AddColumnToJoin(a_ErrorObject, t_JoinedClasses, t_ResultObjs, t_column, t_IndexArray);
t_IndexArray.RemoveAll();
}
}
if (retVal)
{
if (m_bIndicate)
{
POSITION t_pos = t_ResultObjs.GetHeadPosition();
BOOL t_bIndicated = FALSE;
while (t_pos)
{
IWbemClassObject *t_Obj = t_ResultObjs.GetNext(t_pos);
if (t_Obj)
{
if (PostFilter(t_Obj))
{
if (a_bSingle && t_bIndicated)
{
retVal = FALSE;
a_ErrorObject.SetStatus ( WBEM_PROV_E_TOOMANYRESULTSRETURNED ) ;
a_ErrorObject.SetWbemStatus ( WBEM_E_FAILED ) ;
a_ErrorObject.SetMessage ( L"Too many view instances can be created." ) ;
break;
}
else
{
m_NotificationHandler->Indicate(1, &t_Obj);
t_bIndicated = TRUE;
}
}
}
}
}
}
t_ResultObjs.RemoveAll();
}
//clean up...
for (x = 0; x < m_ObjSinkArray.GetSize(); x++)
{
if (m_ObjSinkArray[x] != NULL)
{
m_ObjSinkArray[x]->Release();
}
}
m_ObjSinkArray.RemoveAll();
return retVal;
}
BOOL WbemTaskObject::JoinItem(WbemProvErrorObject &a_ErrorObject,
IWbemClassObject *a_Obj1, IWbemClassObject *a_vObj,
IWbemClassObject *a_resObj, CList <int, int> &a_IndexArray,
DWORD a_indx1)
{
BOOL retVal = TRUE;
wchar_t** t_clsA = m_JoinOnArray.GetAClasses();
wchar_t** t_clsB = m_JoinOnArray.GetBClasses();
UINT* t_ops = m_JoinOnArray.GetOperators();
wchar_t** t_prpsA = m_JoinOnArray.GetAProperties();
wchar_t** t_prpsB = m_JoinOnArray.GetBProperties();
VARIANT t_vA;
VariantInit(&t_vA);
CIMTYPE t_cA;
POSITION t_pos = a_IndexArray.GetHeadPosition();
while (t_pos && retVal)
{
int t_index = a_IndexArray.GetNext(t_pos);
//get the propertyname in the view...
int t_srcindxA = 0;
int t_srcindxB = 0;
if (m_ClassToIndexMap.Lookup(t_clsB[t_index], t_srcindxB) && m_ClassToIndexMap.Lookup(t_clsA[t_index], t_srcindxA))
{
//find t_prpsB[t_index] and get the view property name...
POSITION t_propPos = m_PropertyMap.GetStartPosition();
CStringW t_propName;
while (t_propPos != NULL)
{
CPropertyQualifierItem *t_propProps;
m_PropertyMap.GetNextAssoc(t_propPos, t_propName, t_propProps);
if (!t_propProps->m_SrcPropertyNames[t_srcindxB].IsEmpty() &&
!t_propProps->m_SrcPropertyNames[t_srcindxA].IsEmpty() &&
(_wcsicmp(t_propProps->m_SrcPropertyNames[t_srcindxB], t_prpsB[t_index]) == 0) &&
(_wcsicmp(t_propProps->m_SrcPropertyNames[t_srcindxA], t_prpsA[t_index]) == 0))
{
break;
}
else
{
t_propName.Empty();
}
}
if (!t_propName.IsEmpty() && SUCCEEDED(a_Obj1->Get(t_prpsA[t_index], 0, &t_vA, &t_cA, NULL)) )
{
VARIANT t_vB;
VariantInit(&t_vB);
CIMTYPE t_cB;
if ( SUCCEEDED(a_vObj->Get(t_propName, 0, &t_vB, &t_cB, NULL)) )
{
if (t_cA == t_cB)
{
if (t_ops[t_index] == CJoinOnQualifierArray::EQUALS_OPERATOR)
{
retVal = CompareSimplePropertyValues(&t_vA, &t_vB, t_cA);
}
else //NOT_EQUALS
{
retVal = !CompareSimplePropertyValues(&t_vA, &t_vB, t_cA);
}
}
else
{
retVal = FALSE;
a_ErrorObject.SetStatus ( WBEM_PROV_E_UNEXPECTED ) ;
a_ErrorObject.SetWbemStatus ( WBEM_E_FAILED ) ;
a_ErrorObject.SetMessage ( L"Join properties have different CIM types." ) ;
}
}
else
{
retVal = FALSE;
a_ErrorObject.SetStatus ( WBEM_PROV_E_UNEXPECTED ) ;
a_ErrorObject.SetWbemStatus ( WBEM_E_FAILED ) ;
a_ErrorObject.SetMessage ( L"Failed to get join property from Source." ) ;
}
VariantClear(&t_vA);
VariantClear(&t_vB);
VariantInit(&t_vA);
}
else
{
retVal = FALSE;
a_ErrorObject.SetStatus ( WBEM_PROV_E_UNEXPECTED ) ;
a_ErrorObject.SetWbemStatus ( WBEM_E_FAILED ) ;
a_ErrorObject.SetMessage ( L"Failed to get join property from Source." ) ;
}
}
else
{
retVal = FALSE;
a_ErrorObject.SetStatus ( WBEM_PROV_E_UNEXPECTED ) ;
a_ErrorObject.SetWbemStatus ( WBEM_E_FAILED ) ;
a_ErrorObject.SetMessage ( L"Failed to find source property in view class." ) ;
}
}
VariantClear(&t_vA);
if (retVal)
{
//copy properties from sources to result
POSITION t_propPos = m_PropertyMap.GetStartPosition();
while ((t_propPos != NULL) && retVal)
{
CStringW t_propName;
CPropertyQualifierItem *t_propProps;
m_PropertyMap.GetNextAssoc(t_propPos, t_propName, t_propProps);
if (!t_propProps->m_SrcPropertyNames[a_indx1].IsEmpty())
{
VARIANT t_v;
VariantInit(&t_v);
CIMTYPE t_c;
if ( SUCCEEDED(a_Obj1->Get(t_propProps->m_SrcPropertyNames[a_indx1], 0, &t_v, &t_c, NULL)) )
{
if (((t_v.vt == VT_NULL) || (t_v.vt == VT_EMPTY)) && t_propProps->IsKey())
{
retVal = FALSE;
a_ErrorObject.SetStatus ( WBEM_PROV_E_UNEXPECTED ) ;
a_ErrorObject.SetWbemStatus ( WBEM_E_FAILED ) ;
a_ErrorObject.SetMessage ( L"View key value in source instance is NULL" );
}
else
{
if ( FAILED(a_resObj->Put(t_propName, 0, &t_v, t_c)) )
{
retVal = FALSE;
a_ErrorObject.SetStatus ( WBEM_PROV_E_UNEXPECTED ) ;
a_ErrorObject.SetWbemStatus ( WBEM_E_FAILED ) ;
a_ErrorObject.SetMessage ( L"Failed to put property" );
}
}
VariantClear(&t_v);
}
else
{
retVal = FALSE;
a_ErrorObject.SetStatus ( WBEM_PROV_E_UNEXPECTED ) ;
a_ErrorObject.SetWbemStatus ( WBEM_E_FAILED ) ;
a_ErrorObject.SetMessage ( L"Failed to get property from Source." ) ;
}
}
else
{
continue;
}
}
}
return retVal;
}
BOOL WbemTaskObject::JoinTwoItems(WbemProvErrorObject &a_ErrorObject,
IWbemClassObject *a_Obj1, IWbemClassObject *a_Obj2,
IWbemClassObject *a_resObj, CList <int, int> &a_IndexArray,
DWORD a_indx1, DWORD a_indx2)
{
BOOL retVal = TRUE;
wchar_t** t_clsA = m_JoinOnArray.GetAClasses();
wchar_t** t_clsB = m_JoinOnArray.GetBClasses();
UINT* t_ops = m_JoinOnArray.GetOperators();
wchar_t** t_prpsA = m_JoinOnArray.GetAProperties();
wchar_t** t_prpsB = m_JoinOnArray.GetBProperties();
VARIANT t_vA;
CIMTYPE t_cA;
POSITION t_pos = a_IndexArray.GetHeadPosition();
while (t_pos && retVal)
{
int t_index = a_IndexArray.GetNext(t_pos);
if ( SUCCEEDED(a_Obj1->Get(t_prpsA[t_index], 0, &t_vA, &t_cA, NULL)) )
{
VARIANT t_vB;
CIMTYPE t_cB;
if ( SUCCEEDED(a_Obj2->Get(t_prpsB[t_index], 0, &t_vB, &t_cB, NULL)) )
{
if (t_cA == t_cB)
{
if (t_ops[t_index] == CJoinOnQualifierArray::EQUALS_OPERATOR)
{
retVal = CompareSimplePropertyValues(&t_vA, &t_vB, t_cA);
}
else //NOT_EQUALS
{
retVal = !CompareSimplePropertyValues(&t_vA, &t_vB, t_cA);
}
}
else
{
retVal = FALSE;
a_ErrorObject.SetStatus ( WBEM_PROV_E_UNEXPECTED ) ;
a_ErrorObject.SetWbemStatus ( WBEM_E_FAILED ) ;
a_ErrorObject.SetMessage ( L"Join properties have different CIM types." ) ;
}
VariantClear(&t_vB);
}
else
{
retVal = FALSE;
a_ErrorObject.SetStatus ( WBEM_PROV_E_UNEXPECTED ) ;
a_ErrorObject.SetWbemStatus ( WBEM_E_FAILED ) ;
a_ErrorObject.SetMessage ( L"Failed to get join property from Source." ) ;
}
VariantClear(&t_vA);
}
else
{
retVal = FALSE;
a_ErrorObject.SetStatus ( WBEM_PROV_E_UNEXPECTED ) ;
a_ErrorObject.SetWbemStatus ( WBEM_E_FAILED ) ;
a_ErrorObject.SetMessage ( L"Failed to get join property from Source." ) ;
}
}
if (retVal)
{
//copy properties from sources to result
POSITION t_propPos = m_PropertyMap.GetStartPosition();
while ((t_propPos != NULL) && retVal)
{
CStringW t_propName;
CPropertyQualifierItem *t_propProps;
m_PropertyMap.GetNextAssoc(t_propPos, t_propName, t_propProps);
IWbemClassObject *t_src_Obj = NULL;
DWORD t_index = 0;
if (!t_propProps->m_SrcPropertyNames[a_indx1].IsEmpty())
{
t_src_Obj = a_Obj1;
t_index = a_indx1;
}
else if (!t_propProps->m_SrcPropertyNames[a_indx2].IsEmpty())
{
t_src_Obj = a_Obj2;
t_index = a_indx2;
}
else
{
continue;
}
VARIANT t_v;
VariantInit(&t_v);
CIMTYPE t_c;
if ( SUCCEEDED(t_src_Obj->Get(t_propProps->m_SrcPropertyNames[t_index], 0, &t_v, &t_c, NULL)) )
{
if (((t_v.vt == VT_NULL) || (t_v.vt == VT_EMPTY)) && t_propProps->IsKey())
{
retVal = FALSE;
a_ErrorObject.SetStatus ( WBEM_PROV_E_UNEXPECTED ) ;
a_ErrorObject.SetWbemStatus ( WBEM_E_FAILED ) ;
a_ErrorObject.SetMessage ( L"View key value in source instance is NULL" );
}
else
{
if ( FAILED(a_resObj->Put(t_propName, 0, &t_v, t_c)) )
{
retVal = FALSE;
a_ErrorObject.SetStatus ( WBEM_PROV_E_UNEXPECTED ) ;
a_ErrorObject.SetWbemStatus ( WBEM_E_FAILED ) ;
a_ErrorObject.SetMessage ( L"Failed to put property" );
}
}
VariantClear(&t_v);
}
else
{
retVal = FALSE;
a_ErrorObject.SetStatus ( WBEM_PROV_E_UNEXPECTED ) ;
a_ErrorObject.SetWbemStatus ( WBEM_E_FAILED ) ;
a_ErrorObject.SetMessage ( L"Failed to get property from Source." ) ;
}
}
}
return retVal;
}
BOOL WbemTaskObject::JoinTwoColumns(WbemProvErrorObject &a_ErrorObject,
CMap<CStringW, LPCWSTR, int, int> &a_JoinedClasses,
CList<IWbemClassObject*, IWbemClassObject*> &a_ResultObjs)
{
BOOL retVal = TRUE;
wchar_t** t_clsA = m_JoinOnArray.GetAClasses();
wchar_t** t_clsB = m_JoinOnArray.GetBClasses();
wchar_t** t_prpsA = m_JoinOnArray.GetAProperties();
wchar_t** t_prpsB = m_JoinOnArray.GetBProperties();
UINT* t_ops = m_JoinOnArray.GetOperators();
int t_indexA;
int t_indexB;
CList <int, int> t_IndexArray;
t_IndexArray.AddTail(0);
m_JoinOnArray.m_bDone[0] = TRUE;
for (int x = 1; x < m_JoinOnArray.GetCount(); x++)
{
//find all clauses which can be evaluated now...
if ((_wcsicmp(t_clsA[0], t_clsA[x]) == 0) && (_wcsicmp(t_clsB[0], t_clsB[x]) == 0))
{
t_IndexArray.AddTail(x);
m_JoinOnArray.m_bDone[x] = TRUE;
}
else if ((_wcsicmp(t_clsB[0], t_clsA[x]) == 0) && (_wcsicmp(t_clsA[0], t_clsB[x]) == 0))
{
//want the clauses in the same order for simpler evaluation later...
wchar_t *t_tmp = t_clsA[x];
t_clsA[x] = t_clsB[x];
t_clsB[x] = t_tmp;
t_tmp = t_prpsA[x];
t_prpsA[x] = t_prpsB[x];
t_prpsB[x] = t_tmp;
t_IndexArray.AddTail(x);
m_JoinOnArray.m_bDone[x] = TRUE;
}
}
a_JoinedClasses.SetAt(t_clsA[0], 0);
a_JoinedClasses.SetAt(t_clsB[0], 0);
m_ClassToIndexMap.Lookup(t_clsA[0], t_indexA);
m_ClassToIndexMap.Lookup(t_clsB[0], t_indexB);
for (int i = 0; retVal && (i < m_ObjSinkArray[t_indexA]->m_ObjArray.GetSize()); i++)
{
if (m_ObjSinkArray[t_indexA]->m_ObjArray[i])
{
for (int j = 0; retVal && (j < m_ObjSinkArray[t_indexB]->m_ObjArray.GetSize()); j++)
{
if (m_ObjSinkArray[t_indexB]->m_ObjArray[j])
{
IWbemClassObject* t_viewObj = NULL;
if ( SUCCEEDED(m_ClassObject->SpawnInstance(0, &t_viewObj)) )
{
if (JoinTwoItems(a_ErrorObject, m_ObjSinkArray[t_indexA]->m_ObjArray[i]->GetWrappedObject(),
m_ObjSinkArray[t_indexB]->m_ObjArray[j]->GetWrappedObject(),
t_viewObj, t_IndexArray, t_indexA, t_indexB))
{
a_ResultObjs.AddTail(t_viewObj);
}
else
{
t_viewObj->Release();
}
}
else
{
retVal = FALSE;
a_ErrorObject.SetStatus ( WBEM_PROV_E_UNEXPECTED ) ;
a_ErrorObject.SetWbemStatus ( WBEM_E_FAILED ) ;
a_ErrorObject.SetMessage ( L"An error occured when spawning an instance of the view class." );
}
}
}
m_ObjSinkArray[t_indexA]->m_ObjArray[i]->Release();
m_ObjSinkArray[t_indexA]->m_ObjArray[i] = NULL;
}
}
m_ObjSinkArray[t_indexB]->m_ObjArray.RemoveAll();
return retVal;
}
BOOL WbemTaskObject::AddColumnToJoin(WbemProvErrorObject &a_ErrorObject,
CMap<CStringW, LPCWSTR, int, int> &a_JoinedClasses,
CList<IWbemClassObject*, IWbemClassObject*> &a_ResultObjs,
DWORD a_Index, CList <int, int> &a_IndexArray)
{
BOOL retVal = TRUE;
CList<IWbemClassObject*, IWbemClassObject*> t_AddedResultObjs;
for (int i = 0; retVal && (i < m_ObjSinkArray[a_Index]->m_ObjArray.GetSize()); i++)
{
if (m_ObjSinkArray[a_Index]->m_ObjArray[i])
{
POSITION t_pos = a_ResultObjs.GetHeadPosition();
while (retVal && t_pos)
{
IWbemClassObject *t_vSrc = a_ResultObjs.GetNext(t_pos);
if (t_vSrc)
{
IWbemClassObject* t_viewObj = NULL;
if ( SUCCEEDED(t_vSrc->Clone(&t_viewObj)) )
{
if (JoinItem(a_ErrorObject, m_ObjSinkArray[a_Index]->m_ObjArray[i]->GetWrappedObject(),
t_vSrc, t_viewObj, a_IndexArray, a_Index))
{
t_AddedResultObjs.AddTail(t_viewObj);
}
else
{
t_viewObj->Release();
}
}
else
{
retVal = FALSE;
a_ErrorObject.SetStatus ( WBEM_PROV_E_UNEXPECTED ) ;
a_ErrorObject.SetWbemStatus ( WBEM_E_FAILED ) ;
a_ErrorObject.SetMessage ( L"An error occured when spawning an instance of the view class." );
}
}
}
m_ObjSinkArray[a_Index]->m_ObjArray[i]->Release();
m_ObjSinkArray[a_Index]->m_ObjArray[i] = NULL;
}
}
//don't need partial join any longer
a_ResultObjs.RemoveAll();
//copy the new result set to the result list
//filter if this is the last time here...
if (retVal)
{
POSITION t_pos = t_AddedResultObjs.GetHeadPosition();
while (t_pos)
{
IWbemClassObject *t_vobj = a_ResultObjs.GetNext(t_pos);
if (t_vobj)
{
t_vobj->AddRef();
a_ResultObjs.AddTail(t_vobj);
}
}
}
t_AddedResultObjs.RemoveAll();
return retVal;
}
#else //VP_PERFORMANT_JOINS
BOOL WbemTaskObject::CreateAndIndicateJoins(WbemProvErrorObject &a_ErrorObject, BOOL a_bSingle)
{
BOOL retVal = TRUE;
UINT isize = 1;
if (m_ObjSinkArray.GetSize() != m_SourceArray.GetSize())
{
retVal = FALSE;
a_ErrorObject.SetStatus ( WBEM_PROV_E_UNEXPECTED ) ;
a_ErrorObject.SetWbemStatus ( WBEM_E_FAILED ) ;
a_ErrorObject.SetMessage ( L"A source query failed or was not executed therefore a join could not be created." );
}
//calculate the size of the results
for (UINT x = 0; x < m_ObjSinkArray.GetSize(); x++)
{
if ((m_ObjSinkArray[x] == NULL) || FAILED(m_ObjSinkArray[x]->GetResult()) || !m_ObjSinkArray[x]->m_ObjArray.GetSize())
{
retVal = FALSE;
a_ErrorObject.SetStatus ( WBEM_PROV_E_UNEXPECTED ) ;
a_ErrorObject.SetWbemStatus ( WBEM_E_FAILED ) ;
a_ErrorObject.SetMessage ( L"A source query failed or returned no instances." );
break;
}
if ((0xFFFFFFFF/isize) >= m_ObjSinkArray[x]->m_ObjArray.GetSize())
{
isize = isize * m_ObjSinkArray[x]->m_ObjArray.GetSize();
}
else
{
retVal = FALSE;
a_ErrorObject.SetStatus ( WBEM_PROV_E_UNEXPECTED ) ;
a_ErrorObject.SetWbemStatus ( WBEM_E_FAILED ) ;
a_ErrorObject.SetMessage ( L"Too many possible combinations for join. Provider not capable." );
}
}
if (retVal)
{
IWbemClassObject** objs = new IWbemClassObject*[m_ObjSinkArray.GetSize()];
IWbemClassObject* res_obj = NULL;
int num_res_objs = 0;
for (UINT i = 0; i < isize; i++)
{
UINT t_iDenom = 1;
for (x = 0; x < m_ObjSinkArray.GetSize(); x++)
{
UINT isz = m_ObjSinkArray[x]->m_ObjArray.GetSize();
objs[x] = m_ObjSinkArray[x]->m_ObjArray[(i/t_iDenom) % isz];
t_iDenom = t_iDenom * isz;
}
BOOL t_bRes = CreateAndIndicate(a_ErrorObject, objs, &res_obj);
retVal = retVal && t_bRes;
if (res_obj != NULL)
{
num_res_objs++;
if (a_bSingle)
{
if (num_res_objs > 1)
{
res_obj->Release();
retVal = FALSE;
a_ErrorObject.SetStatus ( WBEM_PROV_E_TOOMANYRESULTSRETURNED ) ;
a_ErrorObject.SetWbemStatus ( WBEM_E_FAILED ) ;
a_ErrorObject.SetMessage ( L"Too many view instances can be created." ) ;
break;
}
}
else
{
if (m_bIndicate)
{
m_NotificationHandler->Indicate(1, &res_obj);
res_obj->Release();
res_obj = NULL;
}
}
}
}
if (a_bSingle)
{
if (num_res_objs == 1)
{
if (m_bIndicate)
{
m_NotificationHandler->Indicate(1, &res_obj);
}
res_obj->Release();
}
}
delete [] objs;
}
for (x = 0; x < m_ObjSinkArray.GetSize(); x++)
{
if (m_ObjSinkArray[x] != NULL)
{
m_ObjSinkArray[x]->Release();
}
}
m_ObjSinkArray.RemoveAll();
return retVal;
}
//for joins
BOOL WbemTaskObject::CreateAndIndicate(WbemProvErrorObject &a_ErrorObject, IWbemClassObject ** pSrcs, IWbemClassObject **pOut)
{
BOOL retVal = TRUE;
wchar_t** clsA = m_JoinOnArray.GetAClasses();
wchar_t** clsB = m_JoinOnArray.GetBClasses();
wchar_t** prpsA = m_JoinOnArray.GetAProperties();
wchar_t** prpsB = m_JoinOnArray.GetBProperties();
UINT* ops = m_JoinOnArray.GetOperators();
for (int x = 0; retVal && (x < m_JoinOnArray.GetCount()); x++)
{
int iA;
int iB;
m_ClassToIndexMap.Lookup(clsA[x], iA);
m_ClassToIndexMap.Lookup(clsB[x], iB);
VARIANT vA;
CIMTYPE cA;
if ( SUCCEEDED(pSrcs[iA]->Get(prpsA[x], 0, &vA, &cA, NULL)) )
{
VARIANT vB;
CIMTYPE cB;
if ( SUCCEEDED(pSrcs[iB]->Get(prpsB[x], 0, &vB, &cB, NULL)) )
{
if (cA == cB)
{
if (ops[x] == CJoinOnQualifierArray::EQUALS_OPERATOR)
{
retVal = CompareSimplePropertyValues(&vA, &vB, cA);
}
else //NOT_EQUALS
{
retVal = !CompareSimplePropertyValues(&vA, &vB, cA);
}
}
else
{
retVal = FALSE;
a_ErrorObject.SetStatus ( WBEM_PROV_E_UNEXPECTED ) ;
a_ErrorObject.SetWbemStatus ( WBEM_E_FAILED ) ;
a_ErrorObject.SetMessage ( L"Join properties have different CIM types." ) ;
}
VariantClear(&vB);
}
else
{
retVal = FALSE;
a_ErrorObject.SetStatus ( WBEM_PROV_E_UNEXPECTED ) ;
a_ErrorObject.SetWbemStatus ( WBEM_E_FAILED ) ;
a_ErrorObject.SetMessage ( L"Failed to get join property from Source." ) ;
}
VariantClear(&vA);
}
else
{
retVal = FALSE;
a_ErrorObject.SetStatus ( WBEM_PROV_E_UNEXPECTED ) ;
a_ErrorObject.SetWbemStatus ( WBEM_E_FAILED ) ;
a_ErrorObject.SetMessage ( L"Failed to get join property from Source." ) ;
}
}
if (retVal)
{
BOOL bIndicate = TRUE;
IWbemClassObject* viewObj = NULL;
if ( SUCCEEDED(m_ClassObject->SpawnInstance(0, &viewObj)) )
{
POSITION propPos = m_PropertyMap.GetStartPosition();
while ((propPos != NULL) && bIndicate)
{
CStringW propName;
CPropertyQualifierItem* propProps;
m_PropertyMap.GetNextAssoc(propPos, propName, propProps);
VARIANT v;
BOOL bSetProp = FALSE;
CIMTYPE c;
for (int x = 0; !bSetProp && (x < propProps->m_SrcPropertyNames.GetSize()); x++)
{
if (!propProps->m_SrcPropertyNames[x].IsEmpty())
{
bSetProp = TRUE;
if ( SUCCEEDED(pSrcs[x]->Get(propProps->m_SrcPropertyNames[x], 0, &v, &c, NULL)) )
{
if (((v.vt == VT_NULL) || (v.vt == VT_EMPTY)) && propProps->IsKey())
{
if (retVal)
{
retVal = FALSE;
a_ErrorObject.SetStatus ( WBEM_PROV_E_UNEXPECTED ) ;
a_ErrorObject.SetWbemStatus ( WBEM_E_FAILED ) ;
a_ErrorObject.SetMessage ( L"View key value in source instance is NULL" );
}
bIndicate = FALSE;
}
else
{
if ( FAILED(viewObj->Put(propName, 0, &v, c)) )
{
if (retVal)
{
retVal = FALSE;
a_ErrorObject.SetStatus ( WBEM_PROV_E_UNEXPECTED ) ;
a_ErrorObject.SetWbemStatus ( WBEM_E_FAILED ) ;
a_ErrorObject.SetMessage ( L"Failed to put property" );
}
if (propProps->IsKey())
{
bIndicate = FALSE;
}
}
}
VariantClear(&v);
}
else
{
if (retVal)
{
retVal = FALSE;
a_ErrorObject.SetStatus ( WBEM_PROV_E_UNEXPECTED ) ;
a_ErrorObject.SetWbemStatus ( WBEM_E_FAILED ) ;
a_ErrorObject.SetMessage ( L"Failed to get property from Source." ) ;
}
}
}
}
}
if (bIndicate)
{
retVal = PostFilter(viewObj);
if (retVal)
{
viewObj->AddRef();
*pOut = viewObj;
}
}
viewObj->Release();
}
else
{
retVal = FALSE;
a_ErrorObject.SetStatus ( WBEM_PROV_E_UNEXPECTED ) ;
a_ErrorObject.SetWbemStatus ( WBEM_E_FAILED ) ;
a_ErrorObject.SetMessage ( L"WBEM API FAILURE:- Failed to spawn an instance of the view class." ) ;
}
}
return retVal;
}
#endif //VP_PERFORMANT_JOINS
BOOL WbemTaskObject::PostFilter(IWbemClassObject* a_pObj)
{
BOOL retVal = TRUE;
if ( (m_RPNPostFilter != NULL) && (m_RPNPostFilter->nNumTokens != 0) )
{
BOOL* t_bStack = new BOOL[m_RPNPostFilter->nNumTokens];
DWORD t_bCnt = 0;
for (int i = 0; retVal && (i < m_RPNPostFilter->nNumTokens); i++)
{
switch (m_RPNPostFilter->pArrayOfTokens[i].nTokenType)
{
case SQL_LEVEL_1_TOKEN::OP_EXPRESSION:
{
t_bStack[t_bCnt] = EvaluateToken(a_pObj, m_RPNPostFilter->pArrayOfTokens[i]);
t_bCnt++;
}
break;
case SQL_LEVEL_1_TOKEN::TOKEN_AND:
{
if (t_bCnt > 1)
{
t_bStack[t_bCnt - 2] = t_bStack[t_bCnt - 1] && t_bStack[t_bCnt - 2];
t_bCnt--;
}
else
{
retVal = FALSE;
}
}
break;
case SQL_LEVEL_1_TOKEN::TOKEN_OR:
{
if (t_bCnt > 1)
{
t_bStack[t_bCnt - 2] = t_bStack[t_bCnt - 1] || t_bStack[t_bCnt - 2];
t_bCnt--;
}
else
{
retVal = FALSE;
}
}
break;
case SQL_LEVEL_1_TOKEN::TOKEN_NOT:
{
if (t_bCnt > 0)
{
t_bStack[t_bCnt - 1] = !t_bStack[t_bCnt - 1];
}
}
break;
default:
{
}
break;
}
}
if (retVal)
{
retVal = t_bStack[t_bCnt - 1];
}
delete [] t_bStack;
}
return retVal;
}