1841 lines
62 KiB
C++
1841 lines
62 KiB
C++
|
|
//***************************************************************************
|
|
//
|
|
// (c) 1999-2001 by Microsoft Corp. All Rights Reserved.
|
|
//
|
|
// eseitrtr.cpp
|
|
//
|
|
// cvadai 19-Mar-99 Created as prototype for Quasar.
|
|
//
|
|
//***************************************************************************
|
|
|
|
#define _ESEIT_CPP_
|
|
#pragma warning( disable : 4786 ) // identifier was truncated to 'number' characters in the
|
|
#pragma warning( disable : 4251 ) // needs to have dll-interface to be used by clients of class
|
|
|
|
#include "precomp.h"
|
|
|
|
#include <std.h>
|
|
#include <smrtptr.h>
|
|
#include <repdrvr.h>
|
|
#include <eseitrtr.h>
|
|
#include <eseutils.h>
|
|
#include <eseobjs.h>
|
|
#include <reputils.h>
|
|
#include <wbemint.h>
|
|
#include <repcache.h>
|
|
#include <like.h>
|
|
#include <datepart.h>
|
|
|
|
typedef std::map <DWORD, DWORD> Properties;
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CWmiESEIterator::CWmiESEIterator
|
|
//
|
|
//***************************************************************************
|
|
|
|
CWmiESEIterator::CWmiESEIterator()
|
|
{
|
|
m_pSession = NULL;
|
|
m_uRefCount = 0;
|
|
m_pConn = NULL;
|
|
m_pToks = NULL;
|
|
m_bFirst = TRUE;
|
|
m_bEnum = FALSE;
|
|
m_bWQL = FALSE;
|
|
m_iStartPos = 0;
|
|
m_iLastPos = 0;
|
|
m_bClasses = FALSE;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CWmiESEIterator::~CWmiESEIterator
|
|
//
|
|
//***************************************************************************
|
|
CWmiESEIterator::~CWmiESEIterator()
|
|
{
|
|
Cancel(0);
|
|
if (m_pSession)
|
|
m_pSession->Release();
|
|
|
|
delete m_pToks;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CWmiESEIterator::QueryInterface
|
|
//
|
|
//***************************************************************************
|
|
|
|
HRESULT STDMETHODCALLTYPE CWmiESEIterator::QueryInterface
|
|
(REFIID riid,
|
|
void __RPC_FAR *__RPC_FAR *ppvObject)
|
|
{
|
|
*ppvObject = 0;
|
|
|
|
if (IID_IUnknown==riid || IID_IWmiDbIterator==riid )
|
|
{
|
|
*ppvObject = (IWmiDbIterator *)this;
|
|
AddRef();
|
|
return S_OK;
|
|
}
|
|
|
|
return E_NOINTERFACE;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CWmiESEIterator::AddRef
|
|
//
|
|
//***************************************************************************
|
|
|
|
ULONG STDMETHODCALLTYPE CWmiESEIterator::AddRef()
|
|
{
|
|
InterlockedIncrement((LONG *) &m_uRefCount);
|
|
return m_uRefCount;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CWmiESEIterator::Release
|
|
//
|
|
//***************************************************************************
|
|
|
|
ULONG STDMETHODCALLTYPE CWmiESEIterator::Release()
|
|
{
|
|
ULONG uNewCount = InterlockedDecrement((LONG *) &m_uRefCount);
|
|
if (0 != uNewCount)
|
|
return uNewCount;
|
|
delete this;
|
|
return WBEM_S_NO_ERROR;
|
|
}
|
|
//***************************************************************************
|
|
//
|
|
// CWmiESEIterator::Cancel
|
|
//
|
|
//***************************************************************************
|
|
|
|
HRESULT STDMETHODCALLTYPE CWmiESEIterator::Cancel(
|
|
/* [in] */ DWORD dwFlags)
|
|
{
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
|
|
if (m_pConn)
|
|
{
|
|
if (m_pSession->m_pController)
|
|
((CWmiDbController *)m_pSession->m_pController)->ConnCache.ReleaseConnection(m_pConn, hr);
|
|
m_pConn = NULL;
|
|
}
|
|
|
|
if (m_pSession)
|
|
((CWmiDbSession *)m_pSession)->UnlockDynasties();
|
|
|
|
return hr;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CWmiESEIterator::NextBatch
|
|
//
|
|
//***************************************************************************
|
|
|
|
HRESULT STDMETHODCALLTYPE CWmiESEIterator::NextBatch(
|
|
/* [in] */ DWORD dwNumRequested,
|
|
/* [in] */ DWORD dwTimeOutSeconds,
|
|
/* [in] */ DWORD dwFlags,
|
|
/* [in] */ DWORD dwRequestedHandleType,
|
|
/* [in] */ REFIID riid,
|
|
/* [out] */ DWORD __RPC_FAR *pdwNumReturned,
|
|
/* [iid_is][length_is][size_is][out] */ LPVOID __RPC_FAR *ppObjects)
|
|
{
|
|
|
|
HRESULT hr = WBEM_S_NO_ERROR, hrRet = WBEM_S_NO_ERROR;
|
|
bool bImmediate = !(dwRequestedHandleType & WMIDB_HANDLE_TYPE_SUBSCOPED);
|
|
|
|
hr = TestDriverStatus();
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
if (!dwNumRequested || !ppObjects)
|
|
return WBEM_E_INVALID_PARAMETER;
|
|
|
|
if (dwRequestedHandleType == WMIDB_HANDLE_TYPE_INVALID &&
|
|
riid == IID_IWmiDbHandle)
|
|
return WBEM_E_INVALID_PARAMETER;
|
|
|
|
if (dwFlags & WMIDB_FLAG_LOOKAHEAD ||
|
|
(riid != IID_IWmiDbHandle &&
|
|
riid != IID_IWbemClassObject &&
|
|
riid != IID__IWmiObject))
|
|
/// UuidCompare(pIIDRequestedInterface, &IID_IWmiDbHandle, NULL) ||
|
|
// UuidCompare(pIIDRequestedInterface, &IID_IWbemClassObject, NULL))
|
|
return WBEM_E_NOT_SUPPORTED;
|
|
|
|
// Read the current row, compare it against m_pToks
|
|
// Continue until we run out of rows, or meet the requested number.
|
|
|
|
LPWSTR lpKey = NULL;
|
|
|
|
try
|
|
{
|
|
SQL_ID dObjectId = 0, dClassId = 0, dScopeId = 0;
|
|
int iNumRetrieved = 0;
|
|
|
|
hr = GetFirstMatch(dObjectId, dClassId, dScopeId, &lpKey);
|
|
while (SUCCEEDED(hr) )
|
|
{
|
|
CDeleteMe <wchar_t> d (lpKey);
|
|
|
|
hr = ((CWmiDbSession *)m_pSession)->VerifyObjectSecurity(NULL, dObjectId, dClassId, dScopeId, 0, WBEM_ENABLE);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
if (FAILED(hr = TestDriverStatus()))
|
|
break;
|
|
|
|
if (riid == IID_IWmiDbHandle)
|
|
{
|
|
CWmiDbHandle *pTemp = new CWmiDbHandle;
|
|
if (pTemp)
|
|
{
|
|
((CWmiDbSession *)m_pSession)->AddRef_Lock();
|
|
DWORD dwVersion = 0;
|
|
// Obtain a lock for this object
|
|
// =============================
|
|
|
|
hr = ((CWmiDbController *)m_pSession->m_pController)->LockCache.AddLock(bImmediate, dObjectId, dwRequestedHandleType, pTemp,
|
|
dScopeId, dClassId, &((CWmiDbController *)m_pSession->m_pController)->SchemaCache, false,
|
|
0, 0, &dwVersion);
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
delete pTemp;
|
|
// If they failed to get a handle, what do we do?
|
|
// Ignore it and continue, I guess.
|
|
hrRet = WBEM_S_PARTIAL_RESULTS;
|
|
ppObjects[iNumRetrieved] = NULL;
|
|
|
|
}
|
|
else
|
|
{
|
|
pTemp->m_pSession = m_pSession;
|
|
pTemp->AddRef();
|
|
((CWmiDbController *)m_pSession->m_pController)->AddHandle();
|
|
pTemp->m_dwVersion = dwVersion;
|
|
pTemp->m_dwHandleType = dwRequestedHandleType;
|
|
pTemp->m_dClassId = dClassId;
|
|
pTemp->m_dObjectId = dObjectId;
|
|
|
|
if (pTemp->m_dClassId == MAPPEDNSCLASSID)
|
|
pTemp->m_bDefault = FALSE;
|
|
if (dwFlags & WBEM_FLAG_USE_SECURITY_DESCRIPTOR)
|
|
pTemp->m_bSecDesc = TRUE;
|
|
|
|
pTemp->m_dScopeId = dScopeId;
|
|
|
|
ppObjects[iNumRetrieved] = pTemp;
|
|
}
|
|
iNumRetrieved++;
|
|
}
|
|
else
|
|
hr = WBEM_E_OUT_OF_MEMORY;
|
|
}
|
|
else if (riid == IID_IWbemClassObject ||
|
|
riid == IID__IWmiObject)
|
|
{
|
|
IWbemClassObject *pTemp = NULL;
|
|
DWORD dwVer = 0;
|
|
|
|
if (m_dwOpenTable == OPENTABLE_CLASSMAP)
|
|
{
|
|
// If this is a class, we need to populate it on
|
|
// a different connection, so we don't lose our
|
|
// pointer into the db.
|
|
|
|
CSQLConnection *pConn = NULL;
|
|
if (((CWmiDbSession *)m_pSession)->m_pController)
|
|
{
|
|
hr = ((CWmiDbController *)((CWmiDbSession *)m_pSession)->m_pController)->ConnCache.GetConnection(&pConn, FALSE, FALSE);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = ((CWmiDbSession *)m_pSession)->GetObjectData(pConn, dObjectId, dClassId, dScopeId,
|
|
0, dwVer, &pTemp, TRUE, lpKey, dwFlags & WBEM_FLAG_USE_SECURITY_DESCRIPTOR);
|
|
|
|
if (((CWmiDbSession *)m_pSession)->m_pController)
|
|
((CWmiDbController *)((CWmiDbSession *)m_pSession)->m_pController)->ConnCache.ReleaseConnection(pConn, hr, FALSE);
|
|
}
|
|
}
|
|
}
|
|
else if (m_dwOpenTable == OPENTABLE_INDEXREF)
|
|
{
|
|
CSQLConnection *pConn = NULL;
|
|
if (((CWmiDbSession *)m_pSession)->m_pController)
|
|
{
|
|
hr = ((CWmiDbController *)((CWmiDbSession *)m_pSession)->m_pController)->ConnCache.GetConnection(&pConn, FALSE, FALSE);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
m_pSession->LoadClassInfo(pConn, dClassId, FALSE);
|
|
|
|
hr = ((CWmiDbSession *)m_pSession)->GetObjectData(pConn, dObjectId, dClassId, dScopeId,
|
|
0, dwVer, &pTemp, TRUE, lpKey, dwFlags & WBEM_FLAG_USE_SECURITY_DESCRIPTOR);
|
|
|
|
if (((CWmiDbSession *)m_pSession)->m_pController)
|
|
((CWmiDbController *)((CWmiDbSession *)m_pSession)->m_pController)->ConnCache.ReleaseConnection(pConn, hr, FALSE);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = ((CWmiDbSession *)m_pSession)->GetObjectData(m_pConn, dObjectId, dClassId, dScopeId,
|
|
0, dwVer, &pTemp, TRUE, lpKey, dwFlags & WBEM_FLAG_USE_SECURITY_DESCRIPTOR);
|
|
|
|
}
|
|
|
|
ppObjects[iNumRetrieved] = pTemp;
|
|
if (FAILED(hr))
|
|
hrRet = WBEM_S_PARTIAL_RESULTS;
|
|
else
|
|
iNumRetrieved++;
|
|
|
|
}
|
|
}
|
|
else
|
|
hrRet = WBEM_S_PARTIAL_RESULTS;
|
|
|
|
hr = TestDriverStatus();
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
if (m_pSession && ((CWmiDbSession *)m_pSession)->m_pController)
|
|
((CWmiDbController *)m_pSession->m_pController)->IncrementHitCount(false);
|
|
}
|
|
else
|
|
break;
|
|
|
|
if (iNumRetrieved == dwNumRequested)
|
|
break;
|
|
|
|
hr = GetNextMatch(dObjectId, dClassId, dScopeId, &lpKey);
|
|
}
|
|
|
|
if (pdwNumReturned)
|
|
*pdwNumReturned = iNumRetrieved;
|
|
|
|
// Null out m_pStatus if there are no more results!!!
|
|
if ((hr == WBEM_S_NO_MORE_DATA || !iNumRetrieved) &&
|
|
hr != WBEM_E_SHUTTING_DOWN)
|
|
{
|
|
hrRet = WBEM_S_NO_MORE_DATA;
|
|
Cancel(0);
|
|
}
|
|
}
|
|
catch (...)
|
|
{
|
|
hr = WBEM_E_CRITICAL_ERROR;
|
|
}
|
|
|
|
return hrRet;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CWmiESEIterator::GetFirstMatch
|
|
//
|
|
//***************************************************************************
|
|
|
|
HRESULT CWmiESEIterator::GetFirstMatch(SQL_ID &dObjectId, SQL_ID &dClassId, SQL_ID &dScopeId,
|
|
LPWSTR * lpKey)
|
|
{
|
|
HRESULT hr = 0;
|
|
|
|
// Loop through the table we have chosen to
|
|
// scan on, and see if any objects match.
|
|
|
|
hr = GetNextMatch(dObjectId, dClassId, dScopeId, lpKey, m_bFirst);
|
|
m_bFirst = FALSE;
|
|
|
|
return hr;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CWmiESEIterator::GetNextMatch
|
|
//
|
|
//***************************************************************************
|
|
|
|
HRESULT CWmiESEIterator::GetNextMatch(SQL_ID &dObjectId, SQL_ID &dClassId,
|
|
SQL_ID &dScopeId, LPWSTR * lpKey, BOOL bFirst)
|
|
{
|
|
HRESULT hr = 0;
|
|
|
|
OBJECTMAP oj;
|
|
CLASSMAP cd;
|
|
CONTAINEROBJ co;
|
|
INDEXDATA id;
|
|
REFERENCEPROPERTIES pm;
|
|
DWORD dwType = 0;
|
|
|
|
if (lpKey)
|
|
*lpKey = NULL;
|
|
|
|
switch(m_dwOpenTable)
|
|
{
|
|
case OPENTABLE_CLASSMAP:
|
|
if (!bFirst)
|
|
hr = GetNext_ClassMap(m_pConn, cd);
|
|
else
|
|
hr = GetClassMapData(m_pConn, ((CESEConnection *)m_pConn)->GetSessionID(), m_tableid, cd);
|
|
|
|
while (SUCCEEDED(hr))
|
|
{
|
|
hr = TestDriverStatus();
|
|
if (FAILED(hr))
|
|
break;
|
|
|
|
hr = GetFirst_ObjectMap(m_pConn, cd.dClassId, oj);
|
|
|
|
if (oj.dObjectId != dObjectId && oj.iObjectState != 2)
|
|
{
|
|
if (ObjectMatches(oj.dObjectId, oj.dClassId, oj.dObjectScopeId))
|
|
{
|
|
dObjectId = oj.dObjectId;
|
|
dClassId = oj.dClassId;
|
|
dScopeId = oj.dObjectScopeId;
|
|
if (lpKey)
|
|
{
|
|
if (oj.sObjectKey)
|
|
{
|
|
LPWSTR lpNew = new wchar_t[wcslen(oj.sObjectKey)+1];
|
|
if (lpNew)
|
|
{
|
|
wcscpy(lpNew, oj.sObjectKey);
|
|
*lpKey = lpNew;
|
|
}
|
|
else
|
|
hr = WBEM_E_OUT_OF_MEMORY;
|
|
}
|
|
}
|
|
|
|
oj.Clear();
|
|
break;
|
|
}
|
|
}
|
|
|
|
oj.Clear();
|
|
hr = GetNext_ClassMap(m_pConn, cd);
|
|
}
|
|
cd.Clear();
|
|
|
|
break;
|
|
case OPENTABLE_OBJECTMAP:
|
|
// If here, the query is too complex to evaluate
|
|
// through indices. Scan on each participating
|
|
// class.
|
|
|
|
if (!bFirst)
|
|
hr = GetNext_ObjectMap(m_pConn, oj);
|
|
else
|
|
{
|
|
hr = GetObjectMapData(m_pConn, ((CESEConnection *)m_pConn)->GetSessionID(), m_tableid, oj);
|
|
}
|
|
|
|
while (TRUE)
|
|
{
|
|
while (SUCCEEDED(hr) )
|
|
{
|
|
hr = TestDriverStatus();
|
|
if (FAILED(hr))
|
|
break;
|
|
|
|
if (m_bClasses)
|
|
{
|
|
if (oj.dClassId != 1)
|
|
{
|
|
hr = GetNext_ObjectMap(m_pConn, oj);
|
|
continue;
|
|
}
|
|
}
|
|
|
|
if (oj.dObjectId != dObjectId && oj.iObjectState != 2)
|
|
{
|
|
if (ObjectMatches(oj.dObjectId, oj.dClassId, oj.dObjectScopeId))
|
|
{
|
|
dObjectId = oj.dObjectId;
|
|
dClassId = oj.dClassId;
|
|
dScopeId = oj.dObjectScopeId;
|
|
if (lpKey)
|
|
{
|
|
if (oj.sObjectKey)
|
|
{
|
|
LPWSTR lpNew = new wchar_t[wcslen(oj.sObjectKey)+1];
|
|
if (lpNew)
|
|
{
|
|
wcscpy(lpNew, oj.sObjectKey);
|
|
*lpKey = lpNew;
|
|
}
|
|
else
|
|
hr = WBEM_E_OUT_OF_MEMORY;
|
|
}
|
|
}
|
|
oj.Clear();
|
|
break;
|
|
}
|
|
}
|
|
hr = GetNext_ObjectMap(m_pConn, oj);
|
|
}
|
|
|
|
if (!m_bEnum && hr == WBEM_E_NOT_FOUND)
|
|
{
|
|
// See if there is other class criteria
|
|
// We expect each derived class to be
|
|
// listed as separate tokens.
|
|
|
|
DWORD dwNumToks = m_pToks->GetNumTokens();
|
|
BOOL bEnd = TRUE;
|
|
|
|
for (int i = m_iLastPos+1; i < dwNumToks; i++)
|
|
{
|
|
ESEToken *pTok = m_pToks->GetToken(i);
|
|
if (pTok->tokentype == ESE_EXPR_TYPE_EXPR)
|
|
{
|
|
ESEWQLToken *pTok2 = (ESEWQLToken *)pTok;
|
|
if (pTok2->Value.valuetype == ESE_VALUE_TYPE_SYSPROP)
|
|
{
|
|
if (pTok2->dClassId)
|
|
{
|
|
hr = GetFirst_ObjectMapByClass(m_pConn, pTok2->dClassId, oj);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
m_iLastPos = i;
|
|
bEnd = FALSE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (bEnd)
|
|
break;
|
|
}
|
|
else
|
|
break;
|
|
}
|
|
|
|
break;
|
|
|
|
case OPENTABLE_INDEXNUMERIC:
|
|
case OPENTABLE_INDEXSTRING:
|
|
case OPENTABLE_INDEXREAL:
|
|
case OPENTABLE_INDEXREF:
|
|
|
|
// If here, we should have ANDed criteria
|
|
// only, or an A AND (B OR C) construct.
|
|
// That means we only have to scan once.
|
|
|
|
if (m_dwOpenTable == OPENTABLE_INDEXNUMERIC)
|
|
dwType = SQL_POS_INDEXNUMERIC;
|
|
else if (m_dwOpenTable == OPENTABLE_INDEXSTRING)
|
|
dwType = SQL_POS_INDEXSTRING;
|
|
else if (m_dwOpenTable == OPENTABLE_INDEXREAL)
|
|
dwType = SQL_POS_INDEXREAL;
|
|
else if (m_dwOpenTable == OPENTABLE_INDEXREF)
|
|
dwType = SQL_POS_INDEXREF;
|
|
if (m_tableid)
|
|
{
|
|
if (!bFirst)
|
|
hr = GetNext_IndexData(m_pConn, m_tableid, dwType, id);
|
|
else
|
|
hr = GetIndexData(m_pConn, ((CESEConnection *)m_pConn)->GetSessionID(),
|
|
m_tableid, dwType, id);
|
|
while (SUCCEEDED(hr))
|
|
{
|
|
hr = TestDriverStatus();
|
|
if (FAILED(hr))
|
|
break;
|
|
|
|
if (id.dObjectId != dObjectId)
|
|
{
|
|
hr = GetFirst_ObjectMap(m_pConn, id.dObjectId, oj);
|
|
if ((oj.iObjectState != 2) && ObjectMatches(id.dObjectId, oj.dClassId, oj.dObjectScopeId, &id,
|
|
NULL, &dObjectId, &dClassId, &dScopeId))
|
|
{
|
|
oj.Clear();
|
|
break;
|
|
}
|
|
oj.Clear();
|
|
}
|
|
hr = GetNext_IndexData(m_pConn, m_tableid, dwType, id);
|
|
}
|
|
}
|
|
else
|
|
hr = WBEM_E_INVALID_QUERY;
|
|
break;
|
|
|
|
case OPENTABLE_CONTAINEROBJS:
|
|
if (!bFirst)
|
|
hr = GetNext_ContainerObjs(m_pConn, co);
|
|
else
|
|
hr = GetContainerObjsData(m_pConn, ((CESEConnection *)m_pConn)->GetSessionID(), m_tableid, co);
|
|
while (SUCCEEDED(hr))
|
|
{
|
|
hr = TestDriverStatus();
|
|
if (FAILED(hr))
|
|
break;
|
|
|
|
if (co.dContaineeId != dObjectId)
|
|
{
|
|
hr = GetFirst_ObjectMap(m_pConn, co.dContaineeId, oj);
|
|
if ((oj.iObjectState != 2) && ObjectMatches(co.dContaineeId, oj.dClassId, oj.dObjectScopeId))
|
|
{
|
|
dObjectId = oj.dObjectId;
|
|
dClassId = oj.dClassId;
|
|
dScopeId = oj.dObjectScopeId;
|
|
oj.Clear();
|
|
break;
|
|
}
|
|
oj.Clear();
|
|
}
|
|
hr = GetNext_ContainerObjs(m_pConn, co);
|
|
}
|
|
break;
|
|
case OPENTABLE_REFPROPS:
|
|
if (!bFirst)
|
|
hr = GetNext_ReferenceProperties(m_pConn, pm);
|
|
else
|
|
hr = GetReferencePropertiesData(m_pConn, ((CESEConnection *)m_pConn)->GetSessionID(), m_tableid, pm);
|
|
while (SUCCEEDED(hr))
|
|
{
|
|
hr = TestDriverStatus();
|
|
if (FAILED(hr))
|
|
break;
|
|
|
|
if (pm.dClassId != dObjectId)
|
|
{
|
|
hr = GetFirst_ObjectMap(m_pConn, pm.dClassId, oj);
|
|
if (oj.iObjectState != 2 && ObjectMatches(oj.dObjectId, oj.dClassId, oj.dObjectScopeId, NULL,
|
|
&pm, &dObjectId, &dClassId, &dScopeId))
|
|
{
|
|
oj.Clear();
|
|
break;
|
|
}
|
|
oj.Clear();
|
|
}
|
|
hr = GetNext_ReferenceProperties(m_pConn, pm);
|
|
}
|
|
break;
|
|
default:
|
|
hr = WBEM_E_NOT_FOUND;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CWmiESEIterator::SysMatch
|
|
//
|
|
//***************************************************************************
|
|
|
|
BOOL CWmiESEIterator::SysMatch (SQL_ID dObjectId, SQL_ID dClassId, SQL_ID dScopeId, ESEToken *pToken)
|
|
{
|
|
BOOL bRet = FALSE;
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
ESEWQLToken *pTok = (ESEWQLToken *)pToken;
|
|
|
|
_bstr_t sName;
|
|
|
|
hr = ((CWmiDbSession *)m_pSession)->GetSchemaCache()->GetPropertyInfo
|
|
(pTok->dPropertyId, &sName);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
if (!_wcsicmp(sName, L"__Class"))
|
|
{
|
|
SQL_ID dClass = 0;
|
|
hr = ((CWmiDbSession *)m_pSession)->GetSchemaCache()->GetClassID
|
|
(pTok->Value.sValue, dScopeId, dClass);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// Compare if class or instance.
|
|
if (dClassId == 1)
|
|
bRet = (dClass == dObjectId);
|
|
else
|
|
bRet = (dClass == dClassId);
|
|
}
|
|
}
|
|
else if (!_wcsicmp(sName, L"__SuperClass"))
|
|
{
|
|
CLASSMAP cd;
|
|
SQL_ID dParent = 1, dClass = 1;
|
|
if (wcslen(pTok->Value.sValue))
|
|
{
|
|
hr = ((CWmiDbSession *)m_pSession)->GetSchemaCache()->GetClassID
|
|
(pTok->Value.sValue, dScopeId, dClass);
|
|
if (FAILED(hr))
|
|
{
|
|
if (m_dwOpenTable != OPENTABLE_CLASSMAP)
|
|
{
|
|
hr = GetFirst_ClassMapByName(m_pConn, pTok->Value.sValue, cd);
|
|
dClass = cd.dClassId;
|
|
cd.Clear();
|
|
}
|
|
else
|
|
hr = WBEM_E_NOT_FOUND; // If this was going to match, it would be in the cache...
|
|
}
|
|
}
|
|
if (dClassId == 1)
|
|
hr = ((CWmiDbSession *)m_pSession)->GetSchemaCache()->GetParentId(
|
|
dObjectId, dParent);
|
|
else
|
|
hr = ((CWmiDbSession *)m_pSession)->GetSchemaCache()->GetParentId(
|
|
dClassId, dParent);
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
if (dClassId == 1)
|
|
{
|
|
if (m_dwOpenTable == OPENTABLE_CLASSMAP)
|
|
hr = GetClassMapData(m_pConn, ((CESEConnection *)m_pConn)->GetSessionID(), m_tableid, cd);
|
|
else
|
|
hr = GetFirst_ClassMap(m_pConn, dObjectId, cd);
|
|
}
|
|
else
|
|
hr = GetFirst_ClassMap(m_pConn, dClassId, cd);
|
|
|
|
dParent = cd.dSuperClassId;
|
|
cd.Clear();
|
|
|
|
}
|
|
bRet = (SUCCEEDED(hr) && (dParent == dClass));
|
|
}
|
|
else if (!_wcsicmp(sName, L"__Derivation"))
|
|
{
|
|
SQL_ID dClass = 0;
|
|
hr = ((CWmiDbSession *)m_pSession)->GetSchemaCache()->GetClassID
|
|
(pTok->Value.sValue, dScopeId, dClass);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
if (dClassId == 1)
|
|
{
|
|
if (dObjectId == dClass)
|
|
bRet = TRUE;
|
|
else
|
|
bRet = (BOOL)((CWmiDbController *)m_pSession->m_pController)->
|
|
SchemaCache.IsDerivedClass(dClass, dObjectId);
|
|
}
|
|
else
|
|
{
|
|
if (dClass == dClassId)
|
|
bRet = TRUE;
|
|
else
|
|
bRet = (BOOL)((CWmiDbController *)m_pSession->m_pController)->
|
|
SchemaCache.IsDerivedClass(dClass, dClassId);
|
|
}
|
|
}
|
|
}
|
|
else if (!_wcsicmp(sName, L"__Dynasty"))
|
|
{
|
|
SQL_ID dClass = 0;
|
|
hr = ((CWmiDbSession *)m_pSession)->GetSchemaCache()->GetClassID
|
|
(pTok->Value.sValue, dScopeId, dClass);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
if (dClassId == 1)
|
|
bRet = (BOOL)((CWmiDbController *)m_pSession->m_pController)->
|
|
SchemaCache.IsDerivedClass(dClass, dObjectId);
|
|
else
|
|
bRet = (BOOL)((CWmiDbController *)m_pSession->m_pController)->
|
|
SchemaCache.IsDerivedClass(dClass, dClassId);
|
|
if (bRet)
|
|
{
|
|
SQL_ID dParent = 0;
|
|
hr = ((CWmiDbSession *)m_pSession)->GetSchemaCache()->GetParentId(
|
|
dClass, dParent);
|
|
if (SUCCEEDED(hr) && dParent == 1)
|
|
bRet = TRUE;
|
|
}
|
|
}
|
|
}
|
|
else if (!_wcsicmp(sName, L"__Genus"))
|
|
{
|
|
if (pTok->Value.dValue == 1)
|
|
bRet = (dClassId == 1);
|
|
else
|
|
bRet = (dClassId != 1);
|
|
}
|
|
else if (!_wcsicmp(sName, L"__Server"))
|
|
{
|
|
bRet = (!_wcsicmp(pTok->Value.sValue, m_pSession->m_sMachineName));
|
|
}
|
|
else if (!_wcsicmp(sName, L"__Namespace"))
|
|
{
|
|
bRet = (!_wcsnicmp(pTok->Value.sValue, m_pSession->m_sNamespacePath, wcslen(m_pSession->m_sNamespacePath)));
|
|
if (bRet)
|
|
{
|
|
_bstr_t sName;
|
|
hr = ((CWmiDbSession *)m_pSession)->GetSchemaCache()->GetNamespaceName(dScopeId, &sName);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
WCHAR *pTemp2 = (LPWSTR)pTok->Value.sValue;
|
|
pTemp2 += (wcslen(m_pSession->m_sNamespacePath)+1);
|
|
|
|
bRet = (!_wcsicmp(sName, pTemp2));
|
|
}
|
|
}
|
|
}
|
|
else if (!_wcsicmp(sName, L"__Property_Count"))
|
|
{
|
|
Properties props;
|
|
DWORD dwNumProps = 0;
|
|
if (dClassId == 1)
|
|
{
|
|
hr = ((CWmiDbSession *)m_pSession)->GetSchemaCache()->GetPropertyList(dObjectId, props, &dwNumProps);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
bRet = (dwNumProps == pTok->Value.dValue);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = ((CWmiDbSession *)m_pSession)->GetSchemaCache()->GetPropertyList(dClassId, props, &dwNumProps);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
bRet = (dwNumProps == pTok->Value.dValue);
|
|
}
|
|
}
|
|
|
|
}
|
|
else if (!_wcsicmp(sName, L"__Path"))
|
|
{
|
|
bRet = TRUE; // post-filter, since we don't know our true path.
|
|
}
|
|
else if (!_wcsicmp(sName, L"__RelPath"))
|
|
{
|
|
OBJECTMAP oj;
|
|
hr = GetObjectMapData(m_pConn, ((CESEConnection *)m_pConn)->GetSessionID(), m_tableid, oj);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
WCHAR *pPtr = (LPWSTR)oj.sObjectPath;
|
|
WCHAR *pLast = NULL;
|
|
while (pPtr && *pPtr)
|
|
{
|
|
if (*pPtr == L':')
|
|
pLast = pPtr;
|
|
|
|
pPtr++;
|
|
}
|
|
if (pLast)
|
|
pLast++;
|
|
else
|
|
pLast = (LPWSTR)pTok->Value.sValue;
|
|
|
|
if (pLast)
|
|
bRet = (!_wcsicmp(pTok->Value.sValue, pLast));
|
|
else
|
|
bRet = FALSE;
|
|
|
|
}
|
|
oj.Clear();
|
|
}
|
|
else
|
|
{
|
|
bRet = FALSE; // Others not supported.
|
|
}
|
|
}
|
|
|
|
// We only support equal and not equal for system properties.
|
|
|
|
if (SUCCEEDED(hr) && pTok->optype == WQL_TOK_NE)
|
|
bRet = !bRet;
|
|
|
|
return bRet;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// Match helper functions
|
|
//
|
|
//***************************************************************************
|
|
|
|
BOOL MatchNumeric (SQL_ID dLeft, SQL_ID dRight, DWORD dwOp, SQL_ID dThird=0)
|
|
{
|
|
BOOL bRet = FALSE;
|
|
switch(dwOp)
|
|
{
|
|
case WQL_TOK_BETWEEN:
|
|
bRet = (dLeft >= dRight);
|
|
if (bRet)
|
|
bRet = (dRight >= dThird);
|
|
break;
|
|
case WQL_TOK_EQ:
|
|
bRet = (dLeft == dRight);
|
|
break;
|
|
case WQL_TOK_GT:
|
|
bRet = (dLeft > dRight);
|
|
break;
|
|
case WQL_TOK_GE:
|
|
bRet = (dLeft >= dRight);
|
|
break;
|
|
case WQL_TOK_LT:
|
|
bRet = (dLeft < dRight);
|
|
break;
|
|
case WQL_TOK_LE:
|
|
bRet = (dLeft <= dRight);
|
|
break;
|
|
case WQL_TOK_NE:
|
|
bRet = (dLeft != dRight);
|
|
break;
|
|
}
|
|
|
|
return bRet;
|
|
}
|
|
|
|
BOOL MatchString (LPWSTR lpLeft, LPWSTR lpRight, DWORD dwOp, LPWSTR lpThird=0)
|
|
{
|
|
BOOL bRet = FALSE;
|
|
|
|
if (!lpLeft || !lpRight)
|
|
return FALSE;
|
|
|
|
switch(dwOp)
|
|
{
|
|
case WQL_TOK_BETWEEN:
|
|
bRet = (_wcsicmp(lpRight, lpLeft) >= 0) ? TRUE: FALSE;
|
|
if (bRet)
|
|
bRet = (_wcsicmp(lpRight, lpThird) >= 0)? TRUE: FALSE;
|
|
break;
|
|
case WQL_TOK_LIKE:
|
|
{
|
|
CLike c (lpRight);
|
|
bRet = c.Match(lpLeft);
|
|
}
|
|
break;
|
|
case WQL_TOK_NOT_LIKE:
|
|
{
|
|
CLike c (lpRight);
|
|
bRet = !(c.Match(lpLeft));
|
|
}
|
|
break;
|
|
case WQL_TOK_EQ:
|
|
bRet = (!_wcsicmp(lpLeft, lpRight));
|
|
break;
|
|
case WQL_TOK_GT:
|
|
bRet = (_wcsicmp(lpLeft, lpRight) > 0 ? TRUE: FALSE);
|
|
break;
|
|
case WQL_TOK_GE:
|
|
bRet = (_wcsicmp(lpLeft, lpRight) >= 0 ? TRUE: FALSE);
|
|
break;
|
|
case WQL_TOK_LT:
|
|
bRet = (_wcsicmp(lpLeft, lpRight) < 0 ? TRUE: FALSE);
|
|
break;
|
|
case WQL_TOK_LE:
|
|
bRet = (_wcsicmp(lpLeft, lpRight) <= 0 ? TRUE: FALSE);
|
|
break;
|
|
case WQL_TOK_NE:
|
|
bRet = (_wcsicmp(lpLeft, lpRight));
|
|
break;
|
|
}
|
|
|
|
return bRet;
|
|
}
|
|
|
|
BOOL MatchDouble (double dLeft, double dRight, DWORD dwOp, double dThird=0)
|
|
{
|
|
BOOL bRet = FALSE;
|
|
switch(dwOp)
|
|
{
|
|
case WQL_TOK_BETWEEN:
|
|
bRet = (dRight >= dLeft);
|
|
if (bRet)
|
|
bRet = (dLeft >= dThird);
|
|
break;
|
|
case WQL_TOK_EQ:
|
|
bRet = (dLeft == dRight);
|
|
break;
|
|
case WQL_TOK_GT:
|
|
bRet = (dLeft > dRight);
|
|
break;
|
|
case WQL_TOK_GE:
|
|
bRet = (dLeft >= dRight);
|
|
break;
|
|
case WQL_TOK_LT:
|
|
bRet = (dLeft < dRight);
|
|
break;
|
|
case WQL_TOK_LE:
|
|
bRet = (dLeft <= dRight);
|
|
break;
|
|
case WQL_TOK_NE:
|
|
bRet = (dLeft != dRight);
|
|
break;
|
|
}
|
|
return bRet;
|
|
}
|
|
|
|
SQL_ID GetDatePart(DWORD dwFunc, LPWSTR lpValue)
|
|
{
|
|
int dValue = 0;
|
|
HRESULT hr = 0;
|
|
CDatePart dp;
|
|
|
|
dp.SetDate(lpValue);
|
|
|
|
switch(dwFunc)
|
|
{
|
|
case ESE_FUNCTION_DATEPART_MONTH:
|
|
hr = dp.GetPart(DATEPART_MONTH, &dValue);
|
|
break;
|
|
case ESE_FUNCTION_DATEPART_YEAR:
|
|
hr = dp.GetPart(DATEPART_YEAR, &dValue);
|
|
break;
|
|
case ESE_FUNCTION_DATEPART_DAY:
|
|
hr = dp.GetPart(DATEPART_DAY, &dValue);
|
|
break;
|
|
case ESE_FUNCTION_DATEPART_HOUR:
|
|
hr = dp.GetPart(DATEPART_HOUR, &dValue);
|
|
break;
|
|
case ESE_FUNCTION_DATEPART_MINUTE:
|
|
hr = dp.GetPart(DATEPART_MINUTE, &dValue);
|
|
break;
|
|
case ESE_FUNCTION_DATEPART_SECOND:
|
|
hr = dp.GetPart(DATEPART_SECOND, &dValue);
|
|
break;
|
|
case ESE_FUNCTION_DATEPART_MILLISECOND:
|
|
hr = dp.GetPart(DATEPART_MILLISECOND, &dValue);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (FAILED(hr))
|
|
dValue = -1;
|
|
|
|
return dValue;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CWmiESEIterator::PropMatch
|
|
//
|
|
//***************************************************************************
|
|
|
|
BOOL CWmiESEIterator::PropMatch(CLASSDATA cd, CLASSDATA cd2, ESEWQLToken *pToken)
|
|
{
|
|
BOOL bRet = FALSE;
|
|
|
|
SQL_ID dValue = 0, dCompValue = 0;
|
|
|
|
if (pToken->Value.dwFunc ||
|
|
pToken->CompValue.dwFunc)
|
|
{
|
|
if (cd.sPropertyStringValue)
|
|
dValue = GetDatePart(pToken->Value.dwFunc, cd.sPropertyStringValue);
|
|
if (cd2.sPropertyStringValue)
|
|
dCompValue = GetDatePart(pToken->CompValue.dwFunc, cd2.sPropertyStringValue);
|
|
}
|
|
|
|
switch(pToken->Value.valuetype)
|
|
{
|
|
case ESE_VALUE_TYPE_SQL_ID:
|
|
if (!dValue)
|
|
dValue = cd.dPropertyNumericValue;
|
|
if (!dCompValue)
|
|
dCompValue = cd2.dPropertyNumericValue;
|
|
|
|
bRet = MatchNumeric(dValue, dCompValue,
|
|
pToken->optype, 0);
|
|
|
|
break;
|
|
case ESE_VALUE_TYPE_STRING:
|
|
bRet = MatchString(cd.sPropertyStringValue, cd2.sPropertyStringValue,
|
|
pToken->optype, 0);
|
|
|
|
break;
|
|
case ESE_VALUE_TYPE_REAL:
|
|
bRet = MatchDouble(cd.rPropertyRealValue, cd2.rPropertyRealValue,
|
|
pToken->optype, 0);
|
|
|
|
break;
|
|
default:
|
|
bRet = FALSE;
|
|
break;
|
|
}
|
|
|
|
return bRet;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CWmiESEIterator::Match
|
|
//
|
|
//***************************************************************************
|
|
|
|
BOOL CWmiESEIterator::Match (CLASSDATA cd, ESEToken *pTok)
|
|
{
|
|
BOOL bRet = FALSE;
|
|
|
|
ESEWQLToken *pToken = (ESEWQLToken *)pTok;
|
|
|
|
if (pToken->tokentype == ESE_EXPR_TYPE_EXPR)
|
|
{
|
|
if (pToken->optype == WQL_TOK_ISNULL)
|
|
{
|
|
if (cd.iFlags & ESE_FLAG_NULL)
|
|
bRet = TRUE;
|
|
}
|
|
else if (pToken->optype == WQL_TOK_NOT_NULL)
|
|
{
|
|
if (!(cd.iFlags & ESE_FLAG_NULL))
|
|
bRet = TRUE;
|
|
}
|
|
else
|
|
{
|
|
SQL_ID dValue = 0, dCompValue = 0;
|
|
|
|
if (pToken->Value.dwFunc ||
|
|
pToken->CompValue.dwFunc)
|
|
{
|
|
if (cd.sPropertyStringValue)
|
|
{
|
|
dValue = GetDatePart(pToken->Value.dwFunc, cd.sPropertyStringValue);
|
|
dCompValue = GetDatePart(pToken->CompValue.dwFunc, cd.sPropertyStringValue);
|
|
}
|
|
else
|
|
return FALSE;
|
|
}
|
|
|
|
switch(pToken->Value.valuetype)
|
|
{
|
|
case ESE_VALUE_TYPE_SQL_ID:
|
|
if (!dValue)
|
|
dValue = cd.dPropertyNumericValue;
|
|
|
|
bRet = MatchNumeric(dValue, pToken->Value.dValue,
|
|
pToken->optype, dCompValue);
|
|
|
|
break;
|
|
case ESE_VALUE_TYPE_STRING:
|
|
bRet = MatchString(cd.sPropertyStringValue, pToken->Value.sValue,
|
|
pToken->optype, pToken->CompValue.sValue);
|
|
|
|
break;
|
|
case ESE_VALUE_TYPE_REAL:
|
|
bRet = MatchDouble(cd.rPropertyRealValue, pToken->Value.rValue,
|
|
pToken->optype, pToken->CompValue.rValue);
|
|
|
|
break;
|
|
case ESE_VALUE_TYPE_REF:
|
|
|
|
switch(pToken->optype)
|
|
{
|
|
case WQL_TOK_ISA:
|
|
|
|
bRet = cd.dRefClassId == pToken->Value.dValue;
|
|
if (!bRet)
|
|
{
|
|
bRet = (((CWmiDbSession *)m_pSession)->GetSchemaCache()->IsDerivedClass
|
|
(pToken->Value.dValue, cd.dRefClassId));
|
|
}
|
|
|
|
break;
|
|
}
|
|
break;
|
|
case ESE_VALUE_TYPE_SYSPROP:
|
|
bRet = TRUE; // we already evaluated this.
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return bRet;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CWmiESEIterator::ObjectMatches
|
|
//
|
|
//***************************************************************************
|
|
|
|
BOOL CWmiESEIterator::ObjectMatches (SQL_ID dObjectId, SQL_ID dClassId,
|
|
SQL_ID dScopeId, INDEXDATA *pData,
|
|
REFERENCEPROPERTIES *pPData,SQL_ID *pObjectId,
|
|
SQL_ID *pClassId,SQL_ID *pScopeId)
|
|
{
|
|
SQL_ID d1 = dObjectId, d2 = dClassId, d3 = dScopeId;
|
|
BOOL bRet = FALSE;
|
|
if (m_pToks->GetNumTokens())
|
|
{
|
|
TEMPQLTYPE tok = ESE_TEMPQL_TYPE_NONE;
|
|
|
|
if (m_bWQL)
|
|
bRet = ObjectMatchesWQL(d1, d2, d3);
|
|
else
|
|
{
|
|
if (dClassId == 1)
|
|
bRet = ObjectMatchesClass(d1, d2, d3, pPData);
|
|
else
|
|
bRet = ObjectMatchesRef(d1, d2, d3, pData);
|
|
}
|
|
if (bRet)
|
|
{
|
|
if (pObjectId)
|
|
*pObjectId = d1;
|
|
if (pClassId)
|
|
*pClassId = d2;
|
|
if (pScopeId)
|
|
*pScopeId = d3;
|
|
}
|
|
|
|
}
|
|
else
|
|
bRet = TRUE;
|
|
return bRet;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CWmiESEIterator::ObjectMatchesClass
|
|
//
|
|
//***************************************************************************
|
|
|
|
BOOL CWmiESEIterator::ObjectMatchesClass (SQL_ID &dObjectId, SQL_ID &dClassId, SQL_ID &dScopeId, REFERENCEPROPERTIES*pm)
|
|
{
|
|
BOOL bRet = FALSE;
|
|
|
|
// The class with this ID contains a reference to our target class.
|
|
// * Does the scope match?
|
|
// * Do the other properties match?
|
|
// * What is the actual endpoint (assoc or ref?)
|
|
// => Dealing with a class, we need to look at PropertyMap, as well as
|
|
// ClassData for qualifiers!
|
|
|
|
// NOTE: This is expected to be post-filtered anyway, so we will only
|
|
// perform rudimentary matching.
|
|
|
|
int iNumTokens = m_pToks->GetNumTokens();
|
|
TEMPQLTYPE qltype = m_pToks->GetToken(0)->qltype;
|
|
OBJECTMAP oj;
|
|
HRESULT hr = 0;
|
|
SQL_ID dTargetId;
|
|
_bstr_t sName;
|
|
BOOL bAssoc = FALSE;
|
|
|
|
for (int i = m_iStartPos; i < iNumTokens; i++)
|
|
{
|
|
ESEToken *pTok = m_pToks->GetToken(i);
|
|
if (!(pTok->qltype == ESE_TEMPQL_TYPE_REF ||
|
|
pTok->qltype == ESE_TEMPQL_TYPE_ASSOC))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (pTok->qltype == ESE_TEMPQL_TYPE_ASSOC)
|
|
bAssoc = TRUE;
|
|
|
|
qltype = pTok->qltype;
|
|
bRet = FALSE;
|
|
if (pTok->tokentype == ESE_EXPR_TYPE_EXPR)
|
|
{
|
|
ESETempQLToken *pTok2 = (ESETempQLToken *)pTok;
|
|
switch (pTok2->token)
|
|
{
|
|
case TEMPQL_TOKEN_TARGETID:
|
|
dTargetId = pTok2->dValue;
|
|
if (pm->dRefClassId == dTargetId)
|
|
bRet = TRUE;
|
|
break;
|
|
|
|
case TEMPQL_TOKEN_RESULTCLASS:
|
|
if (qltype == ESE_TEMPQL_TYPE_REF)
|
|
{
|
|
// Is this class ID derived from the one
|
|
// in question?
|
|
|
|
if (dObjectId == pTok2->dValue)
|
|
bRet = TRUE;
|
|
else if (((CWmiDbSession *)m_pSession)->GetSchemaCache()->IsDerivedClass
|
|
(pTok2->dValue, dObjectId))
|
|
bRet = TRUE;
|
|
}
|
|
else
|
|
{
|
|
// We can't move the pointer
|
|
// on PropertyMap, or we will mess up our cursor.
|
|
|
|
bRet = TRUE; // postfilter
|
|
}
|
|
|
|
break;
|
|
case TEMPQL_TOKEN_ROLE:
|
|
// Is the current property ID named the token in question?
|
|
{
|
|
_bstr_t sVal;
|
|
((CWmiDbSession *)m_pSession)->GetSchemaCache()->GetPropertyInfo(pm->iPropertyId, &sVal);
|
|
|
|
if (!_wcsicmp(sVal, pTok2->sValue))
|
|
bRet = TRUE;
|
|
}
|
|
break;
|
|
case TEMPQL_TOKEN_RESULTROLE:
|
|
|
|
// We can't move the pointer
|
|
// on PropertyMap, or we will mess up our cursor.
|
|
|
|
bRet = TRUE; // postfilter
|
|
|
|
break;
|
|
case TEMPQL_TOKEN_ASSOCQUALIFIER:
|
|
case TEMPQL_TOKEN_REQQUALIFIER:
|
|
if (qltype == ESE_TEMPQL_TYPE_REF ||
|
|
pTok2->token == TEMPQL_TOKEN_ASSOCQUALIFIER)
|
|
{
|
|
// Does this association instance have this qualifier?
|
|
CLASSDATA cd;
|
|
hr = GetFirst_ClassData(m_pConn, dObjectId, cd);
|
|
while (SUCCEEDED(hr))
|
|
{
|
|
if (pTok2->dValue == cd.iPropertyId)
|
|
{
|
|
bRet = TRUE;
|
|
cd.Clear();
|
|
break;
|
|
}
|
|
hr = GetNext_ClassData(m_pConn, cd);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// We can't move the pointer
|
|
// on PropertyMap, or we will mess up our cursor.
|
|
|
|
bRet = TRUE; // postfilter
|
|
}
|
|
break;
|
|
case TEMPQL_TOKEN_ASSOCCLASS:
|
|
// Is this association instance derived from this class?
|
|
if (dObjectId == pTok2->dValue)
|
|
bRet = TRUE;
|
|
else if (((CWmiDbSession *)m_pSession)->GetSchemaCache()->IsDerivedClass
|
|
(pTok2->dValue, dObjectId))
|
|
bRet = TRUE;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!bRet)
|
|
break;
|
|
}
|
|
|
|
|
|
// FIXME: If the return object is an association,
|
|
// we need to retrieve the other object.
|
|
|
|
|
|
|
|
return bRet;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CWmiESEIterator::ObjectMatchesWQL
|
|
//
|
|
//***************************************************************************
|
|
|
|
BOOL CWmiESEIterator::ObjectMatchesWQL (SQL_ID dObjectId, SQL_ID dClassId, SQL_ID dScopeId)
|
|
{
|
|
BOOL bRet = FALSE;
|
|
|
|
// Traverse the set of tokens to
|
|
// see if this object matches.
|
|
// Since we do *NOT* want to
|
|
// modify the position of the current
|
|
// index, we will retrieve
|
|
// the data from the ClassData table,
|
|
// and see if it matches in toto.
|
|
|
|
int i = 0;
|
|
int iNumToks = m_pToks->GetNumTokens();
|
|
|
|
int * results = new int [iNumToks];
|
|
if (!results)
|
|
return FALSE;
|
|
|
|
CDeleteMe <int> d (results);
|
|
|
|
for (i = m_iStartPos; i < iNumToks; i++)
|
|
{
|
|
ESEWQLToken *pTok = (ESEWQLToken *)m_pToks->GetToken(i);
|
|
|
|
if (pTok->tokentype == ESE_EXPR_TYPE_EXPR &&
|
|
pTok->optype != WQL_TOK_ISNULL &&
|
|
pTok->Value.valuetype != ESE_VALUE_TYPE_SYSPROP)
|
|
results[i] = 0;
|
|
else
|
|
results[i] = -1;
|
|
}
|
|
|
|
int iNumSysToks = 0, iNumOther = 0;
|
|
|
|
// Prematch on system criteria.
|
|
|
|
BOOL bScopeMatch = FALSE, bClassMatch = FALSE;
|
|
BOOL bScopeCrit = FALSE, bClassCrit = FALSE;
|
|
|
|
for (i = m_iStartPos; i < iNumToks; i++)
|
|
{
|
|
ESEToken *pTok2 = m_pToks->GetToken(i);
|
|
if (!pTok2->qltype && pTok2->tokentype == ESE_EXPR_TYPE_EXPR)
|
|
{
|
|
ESEWQLToken *pTok = (ESEWQLToken *)pTok2;
|
|
if (pTok->Value.valuetype == ESE_VALUE_TYPE_SYSPROP)
|
|
{
|
|
// Make sure class and scope ID match
|
|
// If there are multiple scopes and classes,
|
|
// these are ORed together.
|
|
|
|
if (!dScopeId && (dClassId == 1))
|
|
bScopeMatch = TRUE;
|
|
|
|
if (pTok->dScopeId)
|
|
{
|
|
bScopeCrit = TRUE;
|
|
if (dScopeId == pTok->dScopeId)
|
|
bScopeMatch = TRUE;
|
|
}
|
|
|
|
if (pTok->dClassId)
|
|
{
|
|
bClassCrit = TRUE;
|
|
results[i] = TRUE;
|
|
if (dClassId == pTok->dClassId)
|
|
bClassMatch = TRUE;
|
|
}
|
|
iNumSysToks++;
|
|
}
|
|
else if (pTok->tokentype == ESE_EXPR_TYPE_EXPR)
|
|
iNumOther++;
|
|
}
|
|
}
|
|
|
|
if (!((bScopeMatch || !bScopeCrit) ))
|
|
bRet = FALSE;
|
|
else
|
|
{
|
|
if (iNumSysToks)
|
|
bRet = TRUE;
|
|
|
|
if (iNumOther)
|
|
{
|
|
BOOL bPropToProp = FALSE;
|
|
CLASSDATA cd;
|
|
HRESULT hr = 0;
|
|
hr = GetFirst_ClassData(m_pConn, dObjectId, cd);
|
|
while (SUCCEEDED(hr))
|
|
{
|
|
// See if this property matches any
|
|
// line of criteria.
|
|
|
|
for (i = m_iStartPos; i < iNumToks; i++)
|
|
{
|
|
ESEToken *pTok2 = m_pToks->GetToken(i);
|
|
if (!pTok2->qltype && pTok2->tokentype == ESE_EXPR_TYPE_EXPR)
|
|
{
|
|
ESEWQLToken *pTok = (ESEWQLToken *)pTok2;
|
|
if (!pTok->bSysProp)
|
|
{
|
|
if (pTok->dPropertyId == cd.iPropertyId)
|
|
{
|
|
if (!pTok->dCompPropertyId)
|
|
{
|
|
results[i] = Match(cd, pTok);
|
|
cd.Clear();
|
|
}
|
|
else
|
|
bPropToProp = TRUE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
hr = GetNext_ClassData(m_pConn, cd);
|
|
}
|
|
|
|
if (hr == WBEM_E_NOT_FOUND)
|
|
hr = WBEM_S_NO_ERROR;
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// Fishing around for specific property values
|
|
// is pretty expensive, so we do this last.
|
|
// We could optimize this by caching each CLASSDATA
|
|
// as we hit it the first time.
|
|
|
|
if (bPropToProp)
|
|
{
|
|
for (i = m_iStartPos; i < iNumToks; i++)
|
|
{
|
|
if (m_pToks->GetToken(i)->tokentype == ESE_EXPR_TYPE_EXPR)
|
|
{
|
|
ESEWQLToken *pTok = (ESEWQLToken *)m_pToks->GetToken(i);
|
|
if (pTok->dCompPropertyId)
|
|
{
|
|
CLASSDATA cd2;
|
|
hr = GetFirst_ClassData(m_pConn, dObjectId, cd, pTok->dPropertyId);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = GetFirst_ClassData(m_pConn, dObjectId, cd2, pTok->dCompPropertyId);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
results[i] = PropMatch (cd, cd2, pTok);
|
|
cd2.Clear();
|
|
}
|
|
else
|
|
results[i] = FALSE;
|
|
cd.Clear();
|
|
}
|
|
else
|
|
results[i] = FALSE;
|
|
}
|
|
}
|
|
}
|
|
hr = WBEM_S_NO_ERROR;
|
|
}
|
|
}
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// Check for System properties
|
|
for (i = m_iStartPos; i < iNumToks; i++)
|
|
{
|
|
if (m_pToks->GetToken(i)->tokentype == ESE_EXPR_TYPE_EXPR)
|
|
{
|
|
if (((ESEWQLToken *)m_pToks->GetToken(i))->bSysProp == TRUE)
|
|
{
|
|
results[i] = SysMatch(dObjectId, dClassId, dScopeId, m_pToks->GetToken(i));
|
|
}
|
|
// Post-filter ISA stuff.
|
|
if ((((ESEWQLToken *)m_pToks->GetToken(i))->optype) == WQL_TOK_ISA)
|
|
results[i] = TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// Go through the array and make sure
|
|
// we have the results we expected.
|
|
|
|
for (i = m_iStartPos; i < iNumToks; i++)
|
|
{
|
|
ESEToken *pTok = m_pToks->GetToken(i);
|
|
switch(pTok->tokentype)
|
|
{
|
|
case ESE_EXPR_TYPE_AND:
|
|
if (results[i-1] && results[i-2])
|
|
bRet = TRUE;
|
|
else
|
|
bRet = FALSE;
|
|
results[i] = bRet;
|
|
break;
|
|
case ESE_EXPR_TYPE_OR:
|
|
if (results[i-1] || results[i-2])
|
|
bRet = TRUE;
|
|
else
|
|
bRet = FALSE;
|
|
results[i] = bRet;
|
|
break;
|
|
|
|
case ESE_EXPR_TYPE_NOT:
|
|
if (bRet)
|
|
bRet = FALSE;
|
|
else
|
|
bRet = TRUE;
|
|
results[i] = bRet;
|
|
break;
|
|
case ESE_EXPR_TYPE_EXPR:
|
|
bRet = results[i];
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (bClassCrit && !bClassMatch)
|
|
bRet = FALSE;
|
|
}
|
|
|
|
}
|
|
|
|
return bRet;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CWmiESEIterator::ObjectMatchesRef
|
|
//
|
|
//***************************************************************************
|
|
|
|
BOOL CWmiESEIterator::ObjectMatchesRef (SQL_ID &dObjectId, SQL_ID &dClassId,
|
|
SQL_ID &dScopeId, INDEXDATA *pData)
|
|
{
|
|
BOOL bRet = TRUE;
|
|
int iNumTokens = m_pToks->GetNumTokens();
|
|
TEMPQLTYPE qltype = m_pToks->GetToken(0)->qltype;
|
|
OBJECTMAP oj;
|
|
HRESULT hr = 0;
|
|
SQL_ID dTargetId;
|
|
_bstr_t sName;
|
|
BOOL bAssoc = FALSE;
|
|
|
|
for (int i = m_iStartPos; i < iNumTokens; i++)
|
|
{
|
|
ESEToken *pTok = m_pToks->GetToken(i);
|
|
if (!(pTok->qltype == ESE_TEMPQL_TYPE_REF ||
|
|
pTok->qltype == ESE_TEMPQL_TYPE_ASSOC))
|
|
{
|
|
|
|
continue;
|
|
}
|
|
|
|
if (pTok->qltype == ESE_TEMPQL_TYPE_ASSOC)
|
|
bAssoc = TRUE;
|
|
|
|
qltype = pTok->qltype;
|
|
bRet = FALSE;
|
|
if (pTok->tokentype == ESE_EXPR_TYPE_EXPR)
|
|
{
|
|
ESETempQLToken *pTok2 = (ESETempQLToken *)pTok;
|
|
switch (pTok2->token)
|
|
{
|
|
case TEMPQL_TOKEN_TARGETID:
|
|
dTargetId = pTok2->dValue;
|
|
if (pData)
|
|
{
|
|
if (pData->dValue == pTok2->dValue)
|
|
bRet = TRUE;
|
|
}
|
|
break;
|
|
|
|
case TEMPQL_TOKEN_RESULTCLASS:
|
|
if (qltype == ESE_TEMPQL_TYPE_REF)
|
|
{
|
|
// Is this class ID derived from the one
|
|
// in question?
|
|
|
|
if (dClassId == pTok2->dValue)
|
|
bRet = TRUE;
|
|
else if (((CWmiDbSession *)m_pSession)->GetSchemaCache()->IsDerivedClass
|
|
(pTok2->dValue, dClassId))
|
|
bRet = TRUE;
|
|
}
|
|
else
|
|
{
|
|
// Check the other endpoint of the association
|
|
// Get the other endpoint from CLASSDATA
|
|
|
|
CLASSDATA cd;
|
|
hr = GetFirst_ClassData(m_pConn, dObjectId, cd);
|
|
while (SUCCEEDED(hr))
|
|
{
|
|
if (cd.dRefId!= dTargetId)
|
|
{
|
|
hr = GetFirst_ObjectMap(m_pConn, cd.dRefId, oj);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
if (oj.dClassId == pTok2->dValue)
|
|
bRet = TRUE;
|
|
else if (((CWmiDbSession *)m_pSession)->GetSchemaCache()->IsDerivedClass
|
|
(pTok2->dValue, oj.dClassId))
|
|
bRet = TRUE;
|
|
cd.Clear();
|
|
oj.Clear();
|
|
break;
|
|
}
|
|
oj.Clear();
|
|
}
|
|
hr = GetNext_ClassData(m_pConn, cd);
|
|
}
|
|
}
|
|
|
|
break;
|
|
case TEMPQL_TOKEN_ROLE:
|
|
// Is the current property ID named the token in question?
|
|
if (pData)
|
|
{
|
|
hr = ((CWmiDbSession *)m_pSession)->GetSchemaCache()->GetPropertyInfo
|
|
(pData->iPropertyId, &sName);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
if (!_wcsicmp(sName, pTok2->sValue))
|
|
bRet = TRUE;
|
|
}
|
|
}
|
|
break;
|
|
case TEMPQL_TOKEN_RESULTROLE:
|
|
// Is the property ID of the endpoint named the token in question?
|
|
{
|
|
CLASSDATA cd;
|
|
hr = GetFirst_ClassData(m_pConn, dObjectId, cd);
|
|
while (SUCCEEDED(hr))
|
|
{
|
|
if (cd.dRefId != dTargetId)
|
|
{
|
|
hr = ((CWmiDbSession *)m_pSession)->GetSchemaCache()->GetPropertyInfo
|
|
(cd.iPropertyId, &sName);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
if (!_wcsicmp(sName, pTok2->sValue))
|
|
bRet = TRUE;
|
|
cd.Clear();
|
|
break;
|
|
}
|
|
}
|
|
hr = GetNext_ClassData(m_pConn, cd);
|
|
}
|
|
}
|
|
break;
|
|
case TEMPQL_TOKEN_ASSOCQUALIFIER:
|
|
case TEMPQL_TOKEN_REQQUALIFIER:
|
|
if (qltype == ESE_TEMPQL_TYPE_REF ||
|
|
pTok2->token == TEMPQL_TOKEN_ASSOCQUALIFIER)
|
|
{
|
|
// Does this association instance have this qualifier?
|
|
CLASSDATA cd;
|
|
hr = GetFirst_ClassData(m_pConn, dObjectId, cd);
|
|
while (SUCCEEDED(hr))
|
|
{
|
|
if (pTok2->dValue == cd.iPropertyId)
|
|
{
|
|
bRet = TRUE;
|
|
cd.Clear();
|
|
break;
|
|
}
|
|
hr = GetNext_ClassData(m_pConn, cd);
|
|
}
|
|
if (!bRet)
|
|
{
|
|
hr = GetFirst_ClassData(m_pConn, dClassId, cd);
|
|
while (SUCCEEDED(hr))
|
|
{
|
|
if (pTok2->dValue == cd.iPropertyId)
|
|
{
|
|
bRet = TRUE;
|
|
cd.Clear();
|
|
break;
|
|
}
|
|
hr = GetNext_ClassData(m_pConn, cd);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Does the endpoint contain this qualifier?
|
|
CLASSDATA cd;
|
|
hr = GetFirst_ClassData (m_pConn, dObjectId, cd);
|
|
while (SUCCEEDED(hr))
|
|
{
|
|
if (cd.dRefId != dTargetId)
|
|
{
|
|
CLASSDATA cd2;
|
|
hr = GetFirst_ClassData(m_pConn, cd.dRefId, cd2);
|
|
while (SUCCEEDED(hr))
|
|
{
|
|
if (pTok2->dValue == cd2.iPropertyId)
|
|
{
|
|
bRet = TRUE;
|
|
cd2.Clear();
|
|
break;
|
|
}
|
|
hr = GetNext_ClassData(m_pConn, cd2);
|
|
}
|
|
if (!bRet)
|
|
{
|
|
hr = GetFirst_ClassData(m_pConn, cd.dRefClassId, cd2);
|
|
while (SUCCEEDED(hr))
|
|
{
|
|
if (pTok2->dValue == cd2.iPropertyId)
|
|
{
|
|
bRet = TRUE;
|
|
cd2.Clear();
|
|
break;
|
|
}
|
|
hr = GetNext_ClassData(m_pConn, cd2);
|
|
}
|
|
}
|
|
cd.Clear();
|
|
break;
|
|
}
|
|
hr = GetNext_ClassData(m_pConn, cd);
|
|
}
|
|
}
|
|
|
|
break;
|
|
case TEMPQL_TOKEN_ASSOCCLASS:
|
|
// Is this association instance derived from this class?
|
|
if (dClassId == pTok2->dValue)
|
|
bRet = TRUE;
|
|
else if (((CWmiDbSession *)m_pSession)->GetSchemaCache()->IsDerivedClass
|
|
(pTok2->dValue, dClassId))
|
|
bRet = TRUE;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!bRet)
|
|
break;
|
|
}
|
|
|
|
if (bRet && bAssoc)
|
|
{
|
|
CLASSDATA cd;
|
|
hr = GetFirst_ClassData (m_pConn, dObjectId, cd);
|
|
while (SUCCEEDED(hr))
|
|
{
|
|
if (cd.dRefId != dTargetId)
|
|
{
|
|
hr = GetFirst_ObjectMap(m_pConn, cd.dRefId, oj);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
dObjectId = oj.dObjectId;
|
|
dClassId = oj.dClassId;
|
|
dScopeId = oj.dObjectScopeId;
|
|
oj.Clear();
|
|
break;
|
|
}
|
|
oj.Clear();
|
|
}
|
|
hr = GetNext_ClassData(m_pConn, cd);
|
|
}
|
|
cd.Clear();
|
|
|
|
}
|
|
|
|
return bRet;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CWmiESEIterator::TestDriverStatus
|
|
//
|
|
//***************************************************************************
|
|
|
|
HRESULT CWmiESEIterator::TestDriverStatus ()
|
|
{
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
|
|
if (!m_pSession ||
|
|
!(m_pSession->m_pController) ||
|
|
((CWmiDbController *)m_pSession->m_pController)->m_dwCurrentStatus == WBEM_E_SHUTTING_DOWN)
|
|
{
|
|
Cancel(0);
|
|
hr = WBEM_E_SHUTTING_DOWN;
|
|
}
|
|
|
|
return hr;
|
|
}
|