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.
1038 lines
26 KiB
1038 lines
26 KiB
//***************************************************************************
|
|
|
|
//
|
|
|
|
// VPGET.CPP
|
|
|
|
//
|
|
|
|
// Module: WBEM VIEW PROVIDER
|
|
|
|
//
|
|
|
|
// Purpose: Contains the ExecQuery 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 <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 <instpath.h>
|
|
#include <genlex.h>
|
|
#include <sql_1.h>
|
|
#include <objpath.h>
|
|
|
|
#include <vpdefs.h>
|
|
#include <vpquals.h>
|
|
#include <vpserv.h>
|
|
#include <vptasks.h>
|
|
|
|
|
|
//for association work-around
|
|
struct MY_SQL_LEVEL_1_TOKEN
|
|
{
|
|
BOOL m_bSpecial;
|
|
SQL_LEVEL_1_TOKEN m_Tok;
|
|
|
|
MY_SQL_LEVEL_1_TOKEN() { m_bSpecial = FALSE; }
|
|
|
|
//assignment operators
|
|
MY_SQL_LEVEL_1_TOKEN& operator=(SQL_LEVEL_1_TOKEN &Src)
|
|
{
|
|
m_bSpecial = FALSE;
|
|
this->m_Tok = Src;
|
|
return *this;
|
|
}
|
|
|
|
MY_SQL_LEVEL_1_TOKEN& operator=(MY_SQL_LEVEL_1_TOKEN &Src)
|
|
{
|
|
*this = Src.m_Tok;
|
|
m_bSpecial = Src.m_bSpecial;
|
|
return *this;
|
|
}
|
|
|
|
//copy constructors match the operators
|
|
MY_SQL_LEVEL_1_TOKEN(MY_SQL_LEVEL_1_TOKEN &Src) { *this = Src; }
|
|
MY_SQL_LEVEL_1_TOKEN(SQL_LEVEL_1_TOKEN &Src) { *this = Src; }
|
|
};
|
|
|
|
ExecQueryTaskObject::ExecQueryTaskObject(CViewProvServ *a_Provider ,
|
|
BSTR a_QueryFormat, BSTR a_Query, ULONG a_Flag,
|
|
IWbemObjectSink *a_NotificationHandler, IWbemContext *pCtx
|
|
)
|
|
: WbemTaskObject(a_Provider, a_NotificationHandler, a_Flag, pCtx),
|
|
m_Query(NULL),
|
|
m_QueryFormat(NULL),
|
|
m_RPNExpression(NULL)
|
|
{
|
|
m_Query = UnicodeStringDuplicate(a_Query);
|
|
m_QueryFormat = UnicodeStringDuplicate(a_QueryFormat);
|
|
}
|
|
|
|
ExecQueryTaskObject::~ExecQueryTaskObject ()
|
|
{
|
|
BOOL t_Status = TRUE;
|
|
IWbemClassObject *t_NotifyStatus = NULL ;
|
|
|
|
if (WBEM_NO_ERROR != m_ErrorObject.GetWbemStatus ())
|
|
{
|
|
t_Status = GetExtendedNotifyStatusObject ( &t_NotifyStatus ) ;
|
|
}
|
|
|
|
if ( t_Status )
|
|
{
|
|
m_NotificationHandler->SetStatus ( 0 , m_ErrorObject.GetWbemStatus () , 0 , t_NotifyStatus ) ;
|
|
|
|
if (t_NotifyStatus)
|
|
{
|
|
t_NotifyStatus->Release () ;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_NotificationHandler->SetStatus ( 0 , m_ErrorObject.GetWbemStatus () , 0 , NULL ) ;
|
|
}
|
|
|
|
if (m_Query != NULL)
|
|
{
|
|
delete [] m_Query;
|
|
}
|
|
|
|
if (m_QueryFormat != NULL)
|
|
{
|
|
delete [] m_QueryFormat;
|
|
}
|
|
|
|
if (m_RPNExpression != NULL)
|
|
{
|
|
delete m_RPNExpression;
|
|
}
|
|
|
|
if (m_StatusHandle != NULL)
|
|
{
|
|
CloseHandle(m_StatusHandle);
|
|
}
|
|
}
|
|
|
|
BOOL ExecQueryTaskObject::PerformQuery(WbemProvErrorObject &a_ErrorObject)
|
|
{
|
|
BOOL retVal = FALSE;
|
|
m_StatusHandle = CreateEvent(NULL, TRUE, FALSE, NULL);
|
|
retVal = PerformEnumQueries(a_ErrorObject);
|
|
|
|
if (retVal)
|
|
{
|
|
BOOL bWait = TRUE;
|
|
|
|
while (bWait)
|
|
{
|
|
DWORD dwWait = WbemWaitForSingleObject(m_StatusHandle, VP_QUERY_TIMEOUT);
|
|
|
|
switch (dwWait)
|
|
{
|
|
case WAIT_OBJECT_0:
|
|
{
|
|
if (ResetEvent(m_StatusHandle))
|
|
{
|
|
m_ResultReceived = FALSE;
|
|
retVal = PerformSelectQueries(a_ErrorObject, bWait);
|
|
|
|
if (retVal)
|
|
{
|
|
if (bWait)
|
|
{
|
|
while (bWait)
|
|
{
|
|
dwWait = WbemWaitForSingleObject(m_StatusHandle, VP_QUERY_TIMEOUT);
|
|
|
|
switch (dwWait)
|
|
{
|
|
case WAIT_OBJECT_0 :
|
|
{
|
|
retVal = ProcessResults(a_ErrorObject);
|
|
bWait = FALSE;
|
|
}
|
|
break;
|
|
|
|
case WAIT_TIMEOUT:
|
|
{
|
|
BOOL bCleanup = TRUE;
|
|
|
|
if (m_ArrayLock.Lock())
|
|
{
|
|
if (m_ResultReceived)
|
|
{
|
|
m_ResultReceived = FALSE;
|
|
bCleanup = FALSE;
|
|
}
|
|
|
|
m_ArrayLock.Unlock();
|
|
}
|
|
|
|
if (bCleanup)
|
|
{
|
|
CleanUpObjSinks(TRUE);
|
|
a_ErrorObject.SetStatus ( WBEM_PROV_E_FAILED ) ;
|
|
a_ErrorObject.SetWbemStatus ( WBEM_E_FAILED ) ;
|
|
a_ErrorObject.SetMessage ( L"Wait on a sychronization object failed, or query timed out" ) ;
|
|
retVal = FALSE;
|
|
bWait = FALSE;
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
{
|
|
//Cancel outstanding requests and delete object sinks...
|
|
//======================================================
|
|
CleanUpObjSinks(TRUE);
|
|
a_ErrorObject.SetStatus ( WBEM_PROV_E_FAILED ) ;
|
|
a_ErrorObject.SetWbemStatus ( WBEM_E_FAILED ) ;
|
|
a_ErrorObject.SetMessage ( L"Wait on a sychronization object failed" ) ;
|
|
retVal = FALSE;
|
|
bWait = FALSE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
retVal = ProcessResults(a_ErrorObject);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ProcessResults(a_ErrorObject);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
retVal = FALSE;
|
|
a_ErrorObject.SetStatus ( WBEM_PROV_E_INVALID_CLASS ) ;
|
|
a_ErrorObject.SetWbemStatus ( WBEM_E_FAILED ) ;
|
|
a_ErrorObject.SetMessage ( L"Failed to perform source query(ies), a WIN32 API failed" ) ;
|
|
ProcessResults(a_ErrorObject);
|
|
}
|
|
|
|
bWait = FALSE;
|
|
}
|
|
break;
|
|
|
|
case WAIT_TIMEOUT:
|
|
{
|
|
BOOL bCleanup = TRUE;
|
|
|
|
if (m_ArrayLock.Lock())
|
|
{
|
|
if (m_ResultReceived)
|
|
{
|
|
m_ResultReceived = FALSE;
|
|
bCleanup = FALSE;
|
|
}
|
|
|
|
m_ArrayLock.Unlock();
|
|
}
|
|
|
|
if (bCleanup)
|
|
{
|
|
CleanUpObjSinks(TRUE);
|
|
a_ErrorObject.SetStatus ( WBEM_PROV_E_FAILED ) ;
|
|
a_ErrorObject.SetWbemStatus ( WBEM_E_FAILED ) ;
|
|
a_ErrorObject.SetMessage ( L"Wait on a sychronization object failed, or query timed out" ) ;
|
|
retVal = FALSE;
|
|
bWait = FALSE;
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
{
|
|
//Cancel outstanding requests and delete object sinks...
|
|
//======================================================
|
|
CleanUpObjSinks(TRUE);
|
|
a_ErrorObject.SetStatus ( WBEM_PROV_E_FAILED ) ;
|
|
a_ErrorObject.SetWbemStatus ( WBEM_E_FAILED ) ;
|
|
a_ErrorObject.SetMessage ( L"Wait on a sychronization object failed" ) ;
|
|
retVal = FALSE;
|
|
bWait = FALSE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//no outstanding requests, just delete object sinks...
|
|
//====================================================
|
|
CleanUpObjSinks();
|
|
}
|
|
|
|
return retVal;
|
|
}
|
|
|
|
//The following function does 'simple' analysis of the current
|
|
//query and modifies the source queries accordingly...
|
|
//============================================================
|
|
void ExecQueryTaskObject::ModifySourceQueriesForUserQuery()
|
|
{
|
|
MY_SQL_LEVEL_1_TOKEN* pExtraToks = new MY_SQL_LEVEL_1_TOKEN[m_RPNExpression->nNumTokens + 1];
|
|
|
|
for (int x = 0; x < m_NSpaceArray.GetSize(); x++)
|
|
{
|
|
DWORD dwToks = 0;
|
|
BOOL bOptimize = TRUE;
|
|
|
|
for (int i = 0; bOptimize && (i < m_RPNExpression->nNumTokens); i++)
|
|
{
|
|
switch (m_RPNExpression->pArrayOfTokens[i].nTokenType)
|
|
{
|
|
case SQL_LEVEL_1_TOKEN::TOKEN_AND:
|
|
{
|
|
pExtraToks[dwToks++].m_Tok.nTokenType = SQL_LEVEL_1_TOKEN::TOKEN_AND;
|
|
}
|
|
break;
|
|
|
|
case SQL_LEVEL_1_TOKEN::TOKEN_OR:
|
|
{
|
|
pExtraToks[dwToks++].m_Tok.nTokenType = SQL_LEVEL_1_TOKEN::TOKEN_OR;
|
|
}
|
|
break;
|
|
|
|
case SQL_LEVEL_1_TOKEN::TOKEN_NOT:
|
|
{
|
|
pExtraToks[dwToks++].m_Tok.nTokenType = SQL_LEVEL_1_TOKEN::TOKEN_NOT;
|
|
}
|
|
break;
|
|
|
|
case SQL_LEVEL_1_TOKEN::OP_EXPRESSION:
|
|
{
|
|
CPropertyQualifierItem* propItem;
|
|
|
|
if (m_PropertyMap.Lookup(m_RPNExpression->pArrayOfTokens[i].pPropertyName, propItem))
|
|
{
|
|
if (!propItem->m_SrcPropertyNames[x].IsEmpty())
|
|
{
|
|
//TransposeReference if necessary
|
|
//=================================
|
|
MY_SQL_LEVEL_1_TOKEN tmpToken = m_RPNExpression->pArrayOfTokens[i];
|
|
BOOL bCont = TRUE;
|
|
|
|
if (m_bAssoc && (propItem->GetCimType() == CIM_REFERENCE))
|
|
{
|
|
bCont = TransposeReference(propItem, m_RPNExpression->pArrayOfTokens[i].vConstValue,
|
|
&(tmpToken.m_Tok.vConstValue), FALSE, NULL);
|
|
|
|
if (bCont)
|
|
{
|
|
//mark the token as special
|
|
//for the association work-around
|
|
tmpToken.m_bSpecial = TRUE;
|
|
}
|
|
}
|
|
|
|
if (bCont)
|
|
{
|
|
pExtraToks[dwToks] = tmpToken;
|
|
SysFreeString(pExtraToks[dwToks].m_Tok.pPropertyName);
|
|
pExtraToks[dwToks++].m_Tok.pPropertyName = propItem->m_SrcPropertyNames[x].AllocSysString();
|
|
}
|
|
else
|
|
{
|
|
//can't "simply" optimize this query!
|
|
dwToks = 0;
|
|
bOptimize = FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//can't "simply" optimize this query!
|
|
dwToks = 0;
|
|
bOptimize = FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//can't "simply" optimize this query!
|
|
dwToks = 0;
|
|
bOptimize = FALSE;
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
{
|
|
}
|
|
}
|
|
}
|
|
|
|
if (dwToks != 0)
|
|
{
|
|
if (m_SourceArray[x]->GetRPNExpression()->nNumTokens > 0)
|
|
{
|
|
pExtraToks[dwToks++].m_Tok.nTokenType = SQL_LEVEL_1_TOKEN::TOKEN_AND;
|
|
}
|
|
|
|
for (i = 0; i < dwToks; i++)
|
|
{
|
|
m_SourceArray[x]->GetRPNExpression()->AddToken(pExtraToks[i].m_Tok);
|
|
|
|
if (pExtraToks[i].m_bSpecial)
|
|
{
|
|
//add the extra tokens if neccessary
|
|
//for the association work-around
|
|
wchar_t *t_pChar = pExtraToks[i].m_Tok.vConstValue.bstrVal;
|
|
|
|
//must be \\server\namespace and not \\.\namespace or relpath
|
|
if ( (*t_pChar == L'\\') && (*(t_pChar+1) == L'\\') && (*(t_pChar+2) != L'.') )
|
|
{
|
|
//add the dotted version
|
|
SQL_LEVEL_1_TOKEN t_Tok = pExtraToks[i].m_Tok;
|
|
t_pChar = t_Tok.vConstValue.bstrVal + 2;
|
|
|
|
while (*t_pChar != L'\\')
|
|
{
|
|
t_pChar++;
|
|
}
|
|
|
|
--t_pChar;
|
|
*t_pChar = L'.';
|
|
--t_pChar;
|
|
*t_pChar = L'\\';
|
|
--t_pChar;
|
|
*t_pChar = L'\\';
|
|
BSTR t_strtmp = SysAllocString(t_pChar);
|
|
VariantClear(&(t_Tok.vConstValue));
|
|
VariantInit(&(t_Tok.vConstValue));
|
|
t_Tok.vConstValue.vt = VT_BSTR;
|
|
t_Tok.vConstValue.bstrVal = t_strtmp;
|
|
m_SourceArray[x]->GetRPNExpression()->AddToken(t_Tok);
|
|
|
|
//add an Or token
|
|
SQL_LEVEL_1_TOKEN t_OrTok;
|
|
t_OrTok.nTokenType = SQL_LEVEL_1_TOKEN::TOKEN_OR;
|
|
m_SourceArray[x]->GetRPNExpression()->AddToken(t_OrTok);
|
|
|
|
//add the relpath version
|
|
t_pChar = t_Tok.vConstValue.bstrVal + 4;
|
|
|
|
while (*t_pChar != L':')
|
|
{
|
|
t_pChar++;
|
|
}
|
|
|
|
//exclude the ':'
|
|
t_pChar++;
|
|
t_strtmp = SysAllocString(t_pChar);
|
|
VariantClear(&(t_Tok.vConstValue));
|
|
VariantInit(&(t_Tok.vConstValue));
|
|
t_Tok.vConstValue.vt = VT_BSTR;
|
|
t_Tok.vConstValue.bstrVal = t_strtmp;
|
|
m_SourceArray[x]->GetRPNExpression()->AddToken(t_Tok);
|
|
|
|
//add the last OR
|
|
m_SourceArray[x]->GetRPNExpression()->AddToken(t_OrTok);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
delete [] pExtraToks;
|
|
}
|
|
|
|
//This function does 'simple' analysis of the join and modifies the
|
|
//unexecuted source queries accordingly for the results received so far...
|
|
//=========================================================================
|
|
void ExecQueryTaskObject::ModifySourceQueriesWithEnumResults()
|
|
{
|
|
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();
|
|
int iEnum; //the index of the enumerated class
|
|
int iMod; //the index of the source query to be modified
|
|
|
|
for (int x = 0; x < m_JoinOnArray.GetCount(); x++)
|
|
{
|
|
BOOL bIsAEnum = m_EnumerateClasses.Lookup(classA[x], iEnum);
|
|
BOOL bIsBEnum = m_EnumerateClasses.Lookup(classB[x], iEnum);
|
|
wchar_t* propEnum;
|
|
wchar_t* propMod;
|
|
|
|
if ( (bIsAEnum && !bIsBEnum) || (!bIsAEnum && bIsBEnum) )
|
|
{
|
|
if (bIsAEnum)
|
|
{
|
|
if (!m_ClassToIndexMap.Lookup(classA[x], iEnum))
|
|
{
|
|
//an error forget this case!
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
if (!m_ClassToIndexMap.Lookup(classB[x], iMod))
|
|
{
|
|
//an error forget this case!
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
propEnum = propsA[x];
|
|
propMod = propsB[x];
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (!m_ClassToIndexMap.Lookup(classB[x], iEnum))
|
|
{
|
|
//an error forget this case!
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
if (!m_ClassToIndexMap.Lookup(classA[x], iMod))
|
|
{
|
|
//an error forget this case!
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
propEnum = propsB[x];
|
|
propMod = propsA[x];
|
|
}
|
|
}
|
|
}
|
|
|
|
//don't transpose references as
|
|
//they are already in source format.
|
|
int m = 0;
|
|
SQL_LEVEL_1_TOKEN opToken;
|
|
opToken.nTokenType = SQL_LEVEL_1_TOKEN::TOKEN_OR;
|
|
SQL_LEVEL_1_TOKEN token;
|
|
token.nTokenType = SQL_LEVEL_1_TOKEN::OP_EXPRESSION;
|
|
token.pPropertyName = SysAllocString(propMod);
|
|
|
|
if (ops[x] == CJoinOnQualifierArray::NOT_EQUALS_OPERATOR)
|
|
{
|
|
token.nOperator = SQL_LEVEL_1_TOKEN::OP_NOT_EQUAL;
|
|
}
|
|
else if (ops[x] == CJoinOnQualifierArray::EQUALS_OPERATOR)
|
|
{
|
|
token.nOperator = SQL_LEVEL_1_TOKEN::OP_EQUAL;
|
|
}
|
|
|
|
BOOL bAddAnd = m_SourceArray[iMod]->GetRPNExpression()->nNumTokens > 0;
|
|
|
|
for (int n = 0; n < m_ObjSinkArray[iEnum]->m_ObjArray.GetSize(); n++)
|
|
{
|
|
VariantInit(&token.vConstValue);
|
|
IWbemClassObject* pObj = m_ObjSinkArray[iEnum]->m_ObjArray[n]->GetWrappedObject();
|
|
|
|
if ( SUCCEEDED(pObj->Get(propEnum, 0, &token.vConstValue, NULL, NULL)) )
|
|
{
|
|
m_SourceArray[iMod]->GetRPNExpression()->AddToken(token);
|
|
m++;
|
|
|
|
if (m > 1)
|
|
{
|
|
m_SourceArray[iMod]->GetRPNExpression()->AddToken(opToken);
|
|
}
|
|
}
|
|
|
|
VariantClear(&token.vConstValue);
|
|
}
|
|
|
|
if ((bAddAnd) && (m != 0))
|
|
{
|
|
opToken.nTokenType = SQL_LEVEL_1_TOKEN::TOKEN_AND;
|
|
m_SourceArray[iMod]->GetRPNExpression()->AddToken(opToken);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
BOOL ExecQueryTaskObject::PerformSelectQueries(WbemProvErrorObject &a_ErrorObject, BOOL &bWait)
|
|
{
|
|
bWait = FALSE;
|
|
|
|
BOOL bStatusSet = FALSE;
|
|
|
|
if (!m_JoinOnArray.IsValid() || m_EnumerateClasses.IsEmpty())
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
ModifySourceQueriesWithEnumResults();
|
|
|
|
//reset number of queries asked and answered
|
|
m_iQueriesAsked = 1;
|
|
m_iQueriesAnswered = 0;
|
|
|
|
for (int x = 0; x < m_NSpaceArray.GetSize(); x++)
|
|
{
|
|
int dummyInt;
|
|
|
|
if (!m_EnumerateClasses.Lookup(m_SourceArray[x]->GetClassName(), dummyInt))
|
|
{
|
|
CStringW queryStr = GetStringFromRPN(m_SourceArray[x]->GetRPNExpression(), 0, NULL);
|
|
CWbemServerWrap** nsPtrs = m_NSpaceArray[x]->GetServerPtrs();
|
|
|
|
if (queryStr.GetLength() > 0)
|
|
{
|
|
for (int m = 0; m < m_NSpaceArray[x]->GetCount(); m++)
|
|
{
|
|
if (nsPtrs[m] != NULL)
|
|
{
|
|
CViewProvObjectSink* pSnk = new CViewProvObjectSink(m_ObjSinkArray[x], nsPtrs[m], m);
|
|
pSnk->AddRef();
|
|
BSTR queryBStr = queryStr.AllocSysString();
|
|
BSTR queryLBStr = SysAllocString(WBEM_QUERY_LANGUAGE_SQL1);
|
|
IWbemObjectSink* pQuerySink = pSnk;
|
|
IWbemContext * t_pCtx = m_Ctx;
|
|
|
|
if (nsPtrs[m]->IsRemote())
|
|
{
|
|
#if 0
|
|
#if _NT_TARGET_VERSION < 500
|
|
pQuerySink = pSnk->Associate();
|
|
#endif
|
|
#endif
|
|
t_pCtx = NULL; //don't use context for remote cimoms
|
|
}
|
|
|
|
IWbemServices *ptmpServ = nsPtrs[m]->GetServerOrProxy();
|
|
|
|
if (ptmpServ)
|
|
{
|
|
if ( pQuerySink )
|
|
{
|
|
HRESULT t_hr = ptmpServ->ExecQueryAsync(queryLBStr, queryBStr, 0, t_pCtx, pQuerySink);
|
|
|
|
if ( FAILED(t_hr) && (HRESULT_FACILITY(t_hr) != FACILITY_ITF) && nsPtrs[m]->IsRemote())
|
|
{
|
|
if ( SUCCEEDED(UpdateConnection(&(nsPtrs[m]), &ptmpServ)) )
|
|
{
|
|
if (ptmpServ)
|
|
{
|
|
t_hr = ptmpServ->ExecQueryAsync(queryLBStr, queryBStr, 0, t_pCtx, pQuerySink);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (SUCCEEDED(t_hr))
|
|
{
|
|
if (m_ArrayLock.Lock())
|
|
{
|
|
m_iQueriesAsked++;
|
|
m_ArrayLock.Unlock();
|
|
}
|
|
else
|
|
{
|
|
pSnk->DisAssociate();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pSnk->DisAssociate();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pSnk->DisAssociate();
|
|
}
|
|
|
|
if (ptmpServ)
|
|
{
|
|
nsPtrs[m]->ReturnServerOrProxy(ptmpServ);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pSnk->DisAssociate();
|
|
}
|
|
|
|
SysFreeString(queryLBStr);
|
|
SysFreeString(queryBStr);
|
|
pSnk->Release();
|
|
}
|
|
else
|
|
{
|
|
a_ErrorObject.SetStatus ( WBEM_PROV_E_INVALID_NAMESPACE ) ;
|
|
a_ErrorObject.SetWbemStatus ( ( WBEMSTATUS ) m_NSpaceArray[x]->GetServerCreationError () ) ;
|
|
a_ErrorObject.SetMessage ( L"Failed to send query, invalid or inaccessible namespace" ) ;
|
|
|
|
bStatusSet = TRUE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (m_ArrayLock.Lock())
|
|
{
|
|
m_iQueriesAsked--;
|
|
|
|
if (m_iQueriesAsked != m_iQueriesAnswered)
|
|
{
|
|
//just in case this was triggerred while we had yet to ask some queries
|
|
ResetEvent(m_StatusHandle);
|
|
}
|
|
else
|
|
{
|
|
//just in case this wasn't triggerred while we were asking queries
|
|
SetEvent(m_StatusHandle);
|
|
}
|
|
|
|
m_ArrayLock.Unlock();
|
|
}
|
|
|
|
if (m_iQueriesAsked == 0)
|
|
{
|
|
if ( ! bStatusSet )
|
|
{
|
|
a_ErrorObject.SetStatus ( WBEM_PROV_E_INVALID_CLASS ) ;
|
|
a_ErrorObject.SetWbemStatus ( WBEM_E_FAILED ) ;
|
|
a_ErrorObject.SetMessage ( L"Failed to perform source query(ies), invalid source namespace(s)" ) ;
|
|
}
|
|
return FALSE;
|
|
}
|
|
else
|
|
{
|
|
bWait = TRUE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL ExecQueryTaskObject::PerformEnumQueries(WbemProvErrorObject &a_ErrorObject)
|
|
{
|
|
m_iQueriesAsked++;
|
|
ModifySourceQueriesForUserQuery();
|
|
m_ObjSinkArray.SetSize(0, m_NSpaceArray.GetSize());
|
|
|
|
BOOL bStatusSet = FALSE;
|
|
|
|
for (int x = 0; x < m_NSpaceArray.GetSize(); x++)
|
|
{
|
|
BOOL bDone = FALSE;
|
|
int dummyInt;
|
|
CObjectSinkResults * objSnk = new CObjectSinkResults(this, x);
|
|
objSnk->AddRef();
|
|
m_ObjSinkArray.SetAtGrow(x, objSnk);
|
|
|
|
if (!m_JoinOnArray.IsValid() || m_EnumerateClasses.IsEmpty() ||
|
|
m_EnumerateClasses.Lookup(m_SourceArray[x]->GetClassName(), dummyInt) )
|
|
{
|
|
CStringW queryStr = GetStringFromRPN(m_SourceArray[x]->GetRPNExpression(), 0, NULL);
|
|
|
|
if (queryStr.GetLength() > 0)
|
|
{
|
|
CWbemServerWrap** nsPtrs = m_NSpaceArray[x]->GetServerPtrs();
|
|
|
|
for (int m = 0; m < m_NSpaceArray[x]->GetCount(); m++)
|
|
{
|
|
if (nsPtrs[m] != NULL)
|
|
{
|
|
CViewProvObjectSink* pSnk = new CViewProvObjectSink(objSnk, nsPtrs[m], m);
|
|
pSnk->AddRef();
|
|
BSTR queryBStr = queryStr.AllocSysString();
|
|
BSTR queryLBStr = SysAllocString(WBEM_QUERY_LANGUAGE_SQL1);
|
|
IWbemObjectSink* pQuerySink = pSnk;
|
|
IWbemContext * t_pCtx = m_Ctx;
|
|
|
|
if (nsPtrs[m]->IsRemote())
|
|
{
|
|
#if 0
|
|
#if _NT_TARGET_VERSION < 500
|
|
pQuerySink = pSnk->Associate();
|
|
#endif
|
|
#endif
|
|
t_pCtx = NULL; //don't use context for remote cimoms
|
|
}
|
|
|
|
IWbemServices *ptmpServ = nsPtrs[m]->GetServerOrProxy();
|
|
|
|
if (ptmpServ)
|
|
{
|
|
if ( pQuerySink )
|
|
{
|
|
HRESULT t_hr = ptmpServ->ExecQueryAsync(queryLBStr, queryBStr, 0, t_pCtx, pQuerySink);
|
|
|
|
if ( FAILED(t_hr) && (HRESULT_FACILITY(t_hr) != FACILITY_ITF) && nsPtrs[m]->IsRemote())
|
|
{
|
|
if ( SUCCEEDED(UpdateConnection(&(nsPtrs[m]), &ptmpServ)) )
|
|
{
|
|
if (ptmpServ)
|
|
{
|
|
t_hr = ptmpServ->ExecQueryAsync(queryLBStr, queryBStr, 0, t_pCtx, pQuerySink);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (SUCCEEDED(t_hr))
|
|
{
|
|
if (m_ArrayLock.Lock())
|
|
{
|
|
m_iQueriesAsked++;
|
|
m_ArrayLock.Unlock();
|
|
}
|
|
else
|
|
{
|
|
pSnk->DisAssociate();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pSnk->DisAssociate();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pSnk->DisAssociate();
|
|
}
|
|
|
|
if (ptmpServ)
|
|
{
|
|
nsPtrs[m]->ReturnServerOrProxy(ptmpServ);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pSnk->DisAssociate();
|
|
}
|
|
|
|
pSnk->Release();
|
|
SysFreeString(queryBStr);
|
|
SysFreeString(queryLBStr);
|
|
}
|
|
else
|
|
{
|
|
a_ErrorObject.SetStatus ( WBEM_PROV_E_INVALID_NAMESPACE ) ;
|
|
a_ErrorObject.SetWbemStatus ( ( WBEMSTATUS ) m_NSpaceArray[x]->GetServerCreationError () ) ;
|
|
a_ErrorObject.SetMessage ( L"Failed to send query, invalid or inaccessible namespace" ) ;
|
|
|
|
bStatusSet = TRUE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (m_ArrayLock.Lock())
|
|
{
|
|
m_iQueriesAsked--;
|
|
|
|
if (m_iQueriesAsked != m_iQueriesAnswered)
|
|
{
|
|
//just in case this was triggerred while we had yet to ask some queries
|
|
ResetEvent(m_StatusHandle);
|
|
}
|
|
else
|
|
{
|
|
//just in case this wasn't triggerred while we were asking queries
|
|
SetEvent(m_StatusHandle);
|
|
}
|
|
|
|
m_ArrayLock.Unlock();
|
|
}
|
|
|
|
if (m_iQueriesAsked == 0)
|
|
{
|
|
if ( ! bStatusSet )
|
|
{
|
|
a_ErrorObject.SetStatus ( WBEM_PROV_E_INVALID_CLASS ) ;
|
|
a_ErrorObject.SetWbemStatus ( WBEM_E_FAILED ) ;
|
|
a_ErrorObject.SetMessage ( L"Failed to perform source query(ies), invalid source namespace(s)" ) ;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL ExecQueryTaskObject::ProcessResults(WbemProvErrorObject &a_ErrorObject)
|
|
{
|
|
BOOL retVal = TRUE;
|
|
int indexCnt = 0;
|
|
|
|
for (int x = 0; retVal && (x < m_ObjSinkArray.GetSize()); x++)
|
|
{
|
|
if (m_ObjSinkArray[x]->IsSet())
|
|
{
|
|
if (SUCCEEDED(m_ObjSinkArray[x]->GetResult()))
|
|
{
|
|
DWORD dwCount = m_ObjSinkArray[x]->m_ObjArray.GetSize();
|
|
|
|
if (0 < dwCount)
|
|
{
|
|
indexCnt++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
retVal = FALSE;
|
|
a_ErrorObject.SetStatus ( WBEM_PROV_E_INVALID_CLASS ) ;
|
|
a_ErrorObject.SetWbemStatus ( ( WBEMSTATUS ) m_ObjSinkArray[x]->GetResult() ) ;
|
|
a_ErrorObject.SetMessage ( L"Object path and Class qualifiers resulted in a failed query." ) ;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
retVal = FALSE;
|
|
a_ErrorObject.SetStatus ( WBEM_PROV_E_INVALID_CLASS ) ;
|
|
a_ErrorObject.SetWbemStatus ( WBEM_E_FAILED ) ;
|
|
a_ErrorObject.SetMessage ( L"Invalid source namespace path OR object path and Class qualifiers resulted in a failed query." ) ;
|
|
}
|
|
}
|
|
|
|
if (0 == indexCnt)
|
|
{
|
|
if (retVal)
|
|
{
|
|
retVal = FALSE;
|
|
a_ErrorObject.SetStatus ( WBEM_PROV_E_NOT_FOUND ) ;
|
|
a_ErrorObject.SetWbemStatus ( WBEM_E_NOT_FOUND ) ;
|
|
a_ErrorObject.SetMessage ( L"No source objects found to support view object path." ) ;
|
|
}
|
|
|
|
CleanUpObjSinks();
|
|
}
|
|
else
|
|
{
|
|
if (m_JoinOnArray.IsValid())
|
|
{
|
|
#ifdef VP_PERFORMANT_JOINS
|
|
BOOL t_bRes = CreateAndIndicateJoinsPerf(a_ErrorObject, m_bSingleton);
|
|
#else
|
|
BOOL t_bRes = CreateAndIndicateJoins(a_ErrorObject, m_bSingleton);
|
|
#endif
|
|
retVal = retVal && t_bRes;
|
|
}
|
|
else //union or association
|
|
{
|
|
if ((m_bSingleton) && (indexCnt > 1))
|
|
{
|
|
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." ) ;
|
|
CleanUpObjSinks();
|
|
}
|
|
else
|
|
{
|
|
BOOL t_bRes = CreateAndIndicateUnions(a_ErrorObject, -1);
|
|
retVal = retVal && t_bRes;
|
|
}
|
|
}
|
|
}
|
|
|
|
return retVal;
|
|
}
|
|
|
|
BOOL ExecQueryTaskObject :: ExecQuery ()
|
|
{
|
|
BOOL t_Status ;
|
|
DebugOut2(
|
|
CViewProvServ::sm_debugLog->WriteFileAndLine (
|
|
|
|
_T(__FILE__),__LINE__,
|
|
_T("ExecQueryTaskObject :: ExecQuery\r\n")
|
|
) ;
|
|
)
|
|
|
|
if ( _wcsicmp ( m_QueryFormat , WBEM_QUERY_LANGUAGE_SQL1 ) == 0 )
|
|
{
|
|
CTextLexSource querySource(m_Query);
|
|
SQL1_Parser sqlParser(&querySource) ;
|
|
t_Status = ! sqlParser.Parse ( & m_RPNExpression ) ;
|
|
|
|
if ( t_Status )
|
|
{
|
|
t_Status = SetClass(m_RPNExpression->bsClassName) ;
|
|
|
|
if ( t_Status )
|
|
{
|
|
t_Status = ParseAndProcessClassQualifiers(m_ErrorObject);
|
|
|
|
if (t_Status)
|
|
{
|
|
t_Status = PerformQuery(m_ErrorObject);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
t_Status = FALSE ;
|
|
m_ErrorObject.SetStatus ( WBEM_PROV_E_INVALID_CLASS ) ;
|
|
m_ErrorObject.SetWbemStatus ( WBEM_E_INVALID_CLASS ) ;
|
|
m_ErrorObject.SetMessage ( L"Unknown Class" ) ;
|
|
DebugOut2(
|
|
CViewProvServ::sm_debugLog->WriteFileAndLine (
|
|
|
|
_T(__FILE__),__LINE__,
|
|
_T("ExecQueryTaskObject :: ExecQuery:Unknown Class\r\n")
|
|
) ;
|
|
)
|
|
}
|
|
}
|
|
else
|
|
{
|
|
t_Status = FALSE ;
|
|
m_ErrorObject.SetStatus ( WBEM_PROV_E_INVALID_QUERY ) ;
|
|
m_ErrorObject.SetWbemStatus ( WBEM_E_PROVIDER_NOT_CAPABLE ) ;
|
|
m_ErrorObject.SetMessage ( L"WQL query was invalid for this provider" ) ;
|
|
DebugOut2(
|
|
CViewProvServ::sm_debugLog->WriteFileAndLine (
|
|
|
|
_T(__FILE__),__LINE__,
|
|
_T("ExecQueryTaskObject :: ExecQuery:WQL query was invalid for this provider\r\n")
|
|
) ;
|
|
)
|
|
}
|
|
}
|
|
else
|
|
{
|
|
t_Status = FALSE ;
|
|
m_ErrorObject.SetStatus ( WBEM_PROV_E_INVALID_QUERY_TYPE ) ;
|
|
m_ErrorObject.SetWbemStatus ( WBEM_E_INVALID_QUERY_TYPE ) ;
|
|
m_ErrorObject.SetMessage ( L"Query Language not supported" ) ;
|
|
DebugOut2(
|
|
CViewProvServ::sm_debugLog->WriteFileAndLine (
|
|
|
|
_T(__FILE__),__LINE__,
|
|
_T("ExecQueryTaskObject :: ExecQuery:Query Language not supported\r\n")
|
|
) ;
|
|
)
|
|
}
|
|
|
|
DebugOut2(
|
|
CViewProvServ::sm_debugLog->WriteFileAndLine (
|
|
|
|
_T(__FILE__),__LINE__,
|
|
_T("ExecQueryTaskObject :: ExecQuery:Returning %lx\r\n"),
|
|
t_Status
|
|
) ;
|
|
)
|
|
|
|
return t_Status ;
|
|
}
|