617 lines
16 KiB
C++
617 lines
16 KiB
C++
|
/*++
|
||
|
|
||
|
Copyright (c) 2000-2001 Microsoft Corporation
|
||
|
|
||
|
Module Name:
|
||
|
|
||
|
instancehelper.cpp
|
||
|
|
||
|
Abstract:
|
||
|
|
||
|
Implementation of:
|
||
|
CInstanceHelper
|
||
|
|
||
|
Author:
|
||
|
|
||
|
Mohit Srivastava 22-Mar-2001
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
--*/
|
||
|
|
||
|
//
|
||
|
// for metabase.h
|
||
|
//
|
||
|
extern "C" {
|
||
|
#include <nt.h>
|
||
|
#include <ntrtl.h>
|
||
|
#include <nturtl.h>
|
||
|
}
|
||
|
|
||
|
#include <comdef.h>
|
||
|
#include "iisfiles.h"
|
||
|
|
||
|
#include "instancehelper.h"
|
||
|
#include "utils.h"
|
||
|
#include "iiswmimsg.h"
|
||
|
|
||
|
#include "globalconstants.h"
|
||
|
#include "adminacl.h"
|
||
|
#include "ipsecurity.h"
|
||
|
#include "metabase.h"
|
||
|
#include "SmartPointer.h"
|
||
|
#include "schemadynamic.h"
|
||
|
|
||
|
extern CDynSchema* g_pDynSch;
|
||
|
|
||
|
CInstanceHelper::CInstanceHelper(
|
||
|
ParsedObjectPath* i_pParsedObjPath,
|
||
|
CWbemServices* i_pNamespace) :
|
||
|
m_PathParser(e_ParserAcceptRelativeNamespace)
|
||
|
/*++
|
||
|
|
||
|
Synopsis:
|
||
|
Use this constructor when you have already parsed the object path.
|
||
|
Caller owns the ParsedObjectPath.
|
||
|
|
||
|
Arguments: [i_pParsedObjPath] -
|
||
|
[i_pNamespace] -
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
Init(i_pParsedObjPath, i_pNamespace);
|
||
|
}
|
||
|
|
||
|
|
||
|
CInstanceHelper::CInstanceHelper(
|
||
|
BSTR i_bstrObjPath,
|
||
|
CWbemServices* i_pNamespace) :
|
||
|
m_PathParser(e_ParserAcceptRelativeNamespace)
|
||
|
/*++
|
||
|
|
||
|
Synopsis:
|
||
|
Use this constructor when have not already parsed the object path.
|
||
|
|
||
|
Arguments: [i_bstrObjPath] -
|
||
|
[i_pNamespace] -
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
DBG_ASSERT(i_bstrObjPath != NULL);
|
||
|
DBG_ASSERT(i_pNamespace != NULL);
|
||
|
|
||
|
TSmartPointer<ParsedObjectPath> spParsedObject;
|
||
|
|
||
|
HRESULT hr = WBEM_S_NO_ERROR;
|
||
|
hr = CUtils::ParserErrToHR( m_PathParser.Parse(i_bstrObjPath, &spParsedObject) );
|
||
|
THROW_ON_ERROR(hr);
|
||
|
|
||
|
Init(spParsedObject, i_pNamespace);
|
||
|
|
||
|
m_pParsedObjPath = spParsedObject;
|
||
|
spParsedObject = NULL;
|
||
|
|
||
|
m_bOwnObjPath = true;
|
||
|
}
|
||
|
|
||
|
void CInstanceHelper::Init(
|
||
|
ParsedObjectPath* i_pParsedObjPath,
|
||
|
CWbemServices* i_pNamespace)
|
||
|
/*++
|
||
|
|
||
|
Synopsis:
|
||
|
Called by constructors.
|
||
|
|
||
|
Arguments: [i_pParsedObjPath] -
|
||
|
[i_pNamespace] -
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
m_pWmiClass = NULL;
|
||
|
m_pWmiAssoc = NULL;
|
||
|
|
||
|
DBG_ASSERT(i_pParsedObjPath != NULL);
|
||
|
DBG_ASSERT(i_pNamespace != NULL);
|
||
|
|
||
|
HRESULT hr = WBEM_S_NO_ERROR;
|
||
|
|
||
|
if(CUtils::GetClass(i_pParsedObjPath->m_pClass,&m_pWmiClass))
|
||
|
{
|
||
|
}
|
||
|
else if(CUtils::GetAssociation(i_pParsedObjPath->m_pClass,&m_pWmiAssoc))
|
||
|
{
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
THROW_ON_ERROR(WBEM_E_INVALID_CLASS);
|
||
|
}
|
||
|
|
||
|
m_pParsedObjPath = i_pParsedObjPath;
|
||
|
m_bOwnObjPath = false;
|
||
|
m_pNamespace = i_pNamespace;
|
||
|
|
||
|
THROW_ON_ERROR(hr);
|
||
|
}
|
||
|
|
||
|
void CInstanceHelper::GetAssociation(
|
||
|
IWbemClassObject** o_ppObj,
|
||
|
bool i_bVerifyLeft, //default(true)
|
||
|
bool i_bVerifyRight) //default(true)
|
||
|
/*++
|
||
|
|
||
|
Synopsis:
|
||
|
Specifying i_bVerifyLeft or i_bVerifyRight can be expensive, especially
|
||
|
during enumeration. If you have already verified prior to calling this
|
||
|
function that the left and/or right parts exist, then set these params
|
||
|
to false.
|
||
|
|
||
|
Arguments: [o_ppObj] - The WMI association that you "indicate" to WMI.
|
||
|
[i_bVerifyLeft] - Verify left part of the association is valid.
|
||
|
[i_bVerifyRight] - Verify right part of association is valid.
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
DBG_ASSERT(o_ppObj != NULL);
|
||
|
|
||
|
CComPtr<IWbemClassObject> spObj; // This is the obj that the client gets back
|
||
|
HRESULT hr = WBEM_S_NO_ERROR;
|
||
|
|
||
|
if(m_pParsedObjPath->m_dwNumKeys < 2)
|
||
|
{
|
||
|
THROW_ON_ERROR(WBEM_E_INVALID_CLASS);
|
||
|
}
|
||
|
|
||
|
KeyRef* pkrLeft = NULL;
|
||
|
KeyRef* pkrRight = NULL;
|
||
|
for(ULONG i = 0; i < m_pParsedObjPath->m_dwNumKeys; i++)
|
||
|
{
|
||
|
KeyRef* pkr = m_pParsedObjPath->m_paKeys[i];
|
||
|
if(pkr->m_pName)
|
||
|
{
|
||
|
if( !pkrLeft &&
|
||
|
_wcsicmp(pkr->m_pName, m_pWmiAssoc->pType->pszLeft) == 0 )
|
||
|
{
|
||
|
pkrLeft = pkr;
|
||
|
}
|
||
|
if( !pkrRight &&
|
||
|
_wcsicmp(pkr->m_pName, m_pWmiAssoc->pType->pszRight) == 0 )
|
||
|
{
|
||
|
pkrRight = pkr;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if( !pkrLeft || !pkrRight ||
|
||
|
pkrLeft->m_vValue.vt != VT_BSTR ||
|
||
|
pkrRight->m_vValue.vt != VT_BSTR ||
|
||
|
pkrLeft->m_vValue.bstrVal == NULL ||
|
||
|
pkrRight->m_vValue.bstrVal == NULL )
|
||
|
{
|
||
|
THROW_ON_ERROR(WBEM_E_INVALID_OBJECT_PATH);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Now verify the two object paths are valid
|
||
|
//
|
||
|
bool abVerify[2];
|
||
|
abVerify[0] = i_bVerifyLeft;
|
||
|
abVerify[1] = i_bVerifyRight;
|
||
|
KeyRef* apKr[2];
|
||
|
apKr[0] = pkrLeft;
|
||
|
apKr[1] = pkrRight;
|
||
|
if(abVerify[0] || abVerify[1])
|
||
|
{
|
||
|
CMetabase metabase;
|
||
|
CComPtr<IWbemClassObject> spObjTemp;
|
||
|
for(ULONG i = 0; i < 2; i++)
|
||
|
{
|
||
|
if(abVerify[i])
|
||
|
{
|
||
|
spObjTemp = NULL;
|
||
|
CInstanceHelper InstanceHelper(apKr[i]->m_vValue.bstrVal, m_pNamespace);
|
||
|
if(InstanceHelper.IsAssoc())
|
||
|
{
|
||
|
THROW_ON_ERROR(WBEM_E_NOT_FOUND);
|
||
|
}
|
||
|
InstanceHelper.GetInstance(
|
||
|
false,
|
||
|
&metabase,
|
||
|
&spObjTemp);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
hr = CUtils::CreateEmptyInstance(m_pParsedObjPath->m_pClass, m_pNamespace, &spObj);
|
||
|
THROW_ON_ERROR(hr);
|
||
|
|
||
|
hr = spObj->Put(pkrLeft->m_pName, 0, &pkrLeft->m_vValue, 0);
|
||
|
THROW_ON_ERROR(hr);
|
||
|
|
||
|
hr = spObj->Put(pkrRight->m_pName, 0, &pkrRight->m_vValue, 0);
|
||
|
THROW_ON_ERROR(hr);
|
||
|
|
||
|
//
|
||
|
// Set out parameters on success
|
||
|
//
|
||
|
*o_ppObj = spObj;
|
||
|
(*o_ppObj)->AddRef();
|
||
|
}
|
||
|
|
||
|
void CInstanceHelper::GetInstance(
|
||
|
bool i_bCreateKeyIfNotExist,
|
||
|
CMetabase* io_pMetabase,
|
||
|
IWbemClassObject** o_ppObj,
|
||
|
SQL_LEVEL_1_RPN_EXPRESSION_EXT* i_pExp) // default(NULL)
|
||
|
/*++
|
||
|
|
||
|
Synopsis:
|
||
|
Will throw an exception on failure (generallly instance not found in mb).
|
||
|
If GetInstance finds the instance in the metabase, but i_pExp was specified,
|
||
|
it is possible *o_ppObj will not be populated with an instance.
|
||
|
This is a SUCCESS case.
|
||
|
|
||
|
Arguments: [i_bCreateKeyIfNotExist] -
|
||
|
[io_pMetabase] -
|
||
|
[o_ppObj] - The only success case where *o_ppObj will be NULL
|
||
|
is if it the instance is found in the metabase but i_pExp
|
||
|
(i.e. a query) is specified and the query doesn't match.
|
||
|
[i_pExp] - An optional query.
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
DBG_ASSERT(o_ppObj != NULL);
|
||
|
DBG_ASSERT(io_pMetabase != NULL);
|
||
|
|
||
|
*o_ppObj = NULL;
|
||
|
CComPtr<IWbemClassObject> spObj;
|
||
|
|
||
|
HRESULT hr = WBEM_S_NO_ERROR;
|
||
|
METABASE_PROPERTY** ppmbp;
|
||
|
_bstr_t bstrMbPath;
|
||
|
METADATA_HANDLE hKey = NULL;
|
||
|
|
||
|
VARIANT vtTrue;
|
||
|
vtTrue.boolVal = VARIANT_TRUE;
|
||
|
vtTrue.vt = VT_BOOL;
|
||
|
|
||
|
hr = CUtils::CreateEmptyInstance(m_pParsedObjPath->m_pClass, m_pNamespace, &spObj);
|
||
|
THROW_ON_ERROR(hr);
|
||
|
|
||
|
CUtils::GetMetabasePath(spObj, m_pParsedObjPath, m_pWmiClass, bstrMbPath);
|
||
|
|
||
|
//
|
||
|
// if AdminACL
|
||
|
//
|
||
|
if( m_pWmiClass->pkt == &METABASE_KEYTYPE_DATA::s_TYPE_AdminACL ||
|
||
|
m_pWmiClass->pkt == &METABASE_KEYTYPE_DATA::s_TYPE_AdminACE
|
||
|
)
|
||
|
{
|
||
|
CAdminACL objACL;
|
||
|
hr = objACL.OpenSD(bstrMbPath);
|
||
|
if(SUCCEEDED(hr))
|
||
|
hr = objACL.GetObjectAsync(spObj, m_pParsedObjPath, m_pWmiClass);
|
||
|
THROW_ON_ERROR(hr);
|
||
|
*o_ppObj = spObj;
|
||
|
(*o_ppObj)->AddRef();
|
||
|
return;
|
||
|
}
|
||
|
//
|
||
|
// if IPSecurity
|
||
|
//
|
||
|
else if( m_pWmiClass->pkt == &METABASE_KEYTYPE_DATA::s_TYPE_IPSecurity )
|
||
|
{
|
||
|
CIPSecurity IPSecurity;
|
||
|
hr = IPSecurity.OpenSD(bstrMbPath, *io_pMetabase);
|
||
|
if(SUCCEEDED(hr))
|
||
|
hr = IPSecurity.GetObjectAsync(spObj);
|
||
|
THROW_ON_ERROR(hr);
|
||
|
*o_ppObj = spObj;
|
||
|
(*o_ppObj)->AddRef();
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if(!i_bCreateKeyIfNotExist)
|
||
|
{
|
||
|
hKey = io_pMetabase->OpenKey(bstrMbPath, false);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
hKey = io_pMetabase->CreateKey(bstrMbPath);
|
||
|
}
|
||
|
|
||
|
_variant_t vt;
|
||
|
|
||
|
//
|
||
|
// If anything throws, CacheFree and then CloseKey is called automatically
|
||
|
//
|
||
|
io_pMetabase->CacheInit(hKey);
|
||
|
|
||
|
//
|
||
|
// Make sure requested keytype matches the keytype set at the node
|
||
|
//
|
||
|
if(!i_bCreateKeyIfNotExist)
|
||
|
{
|
||
|
io_pMetabase->Get(hKey, &METABASE_PROPERTY_DATA::s_KeyType, m_pNamespace, vt, NULL, NULL);
|
||
|
if( vt.vt != VT_BSTR ||
|
||
|
vt.bstrVal == NULL ||
|
||
|
!CUtils::CompareKeyType(vt.bstrVal, m_pWmiClass->pkt) )
|
||
|
{
|
||
|
CIIsProvException e;
|
||
|
e.SetMC(WBEM_E_NOT_FOUND, IISWMI_INVALID_KEYTYPE, NULL);
|
||
|
throw e;
|
||
|
}
|
||
|
vt.Clear();
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// User wants to filter number of instances returned
|
||
|
// Walk thru all filters, and try and get these first.
|
||
|
//
|
||
|
if(i_pExp && !i_pExp->GetContainsOrOrNot())
|
||
|
{
|
||
|
SQL_LEVEL_1_TOKEN* pToken = i_pExp->pArrayOfTokens;
|
||
|
METABASE_PROPERTY* pMbpQuery = NULL;
|
||
|
for(int i = 0; i < i_pExp->nNumTokens; i++, pToken++)
|
||
|
{
|
||
|
BOOL bInherited = false;
|
||
|
BOOL bDefault = false;
|
||
|
if( pToken->nTokenType == SQL_LEVEL_1_TOKEN::OP_EXPRESSION )
|
||
|
{
|
||
|
hr = g_pDynSch->GetHashProps()->Wmi_GetByKey(
|
||
|
pToken->pPropertyName,
|
||
|
&pMbpQuery);
|
||
|
//
|
||
|
// User requested a property that is not in the schema
|
||
|
//
|
||
|
if(FAILED(hr))
|
||
|
{
|
||
|
DBGPRINTF( (DBG_CONTEXT,
|
||
|
"Property %ws not in schema\n", pToken->pPropertyName) );
|
||
|
THROW_ON_ERROR(WBEM_E_INVALID_QUERY);
|
||
|
}
|
||
|
|
||
|
io_pMetabase->Get(hKey, pMbpQuery, m_pNamespace, vt, &bInherited, &bDefault);
|
||
|
|
||
|
if(!CheckForQueryMatch(pToken, &vt))
|
||
|
{
|
||
|
//
|
||
|
// We don't need to return this instance.
|
||
|
// value from metabase is not what user wanted.
|
||
|
//
|
||
|
io_pMetabase->CacheFree();
|
||
|
io_pMetabase->CloseKey(hKey);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
PutProperty(spObj, pToken->pPropertyName, &vt, bInherited, bDefault);
|
||
|
|
||
|
vt.Clear();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Walk thru all the properties in the class and put them in an instance
|
||
|
// we will return back to WMI
|
||
|
//
|
||
|
for (ppmbp=m_pWmiClass->ppmbp;*ppmbp; ppmbp++)
|
||
|
{
|
||
|
BOOL bInherited = false;
|
||
|
BOOL bDefault = false;
|
||
|
|
||
|
BOOL bSkipProp = false;
|
||
|
if(i_pExp)
|
||
|
{
|
||
|
if(!i_pExp->FindRequestedProperty((*ppmbp)->pszPropName))
|
||
|
{
|
||
|
//
|
||
|
// User did not request this property
|
||
|
//
|
||
|
bSkipProp = true;
|
||
|
}
|
||
|
else if(!i_pExp->GetContainsOrOrNot() && i_pExp->GetFilter((*ppmbp)->pszPropName))
|
||
|
{
|
||
|
//
|
||
|
// Right above for loop, we handled all filters already.
|
||
|
//
|
||
|
bSkipProp = true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if( !bSkipProp )
|
||
|
{
|
||
|
io_pMetabase->Get(hKey, *ppmbp, m_pNamespace, vt, &bInherited, &bDefault);
|
||
|
|
||
|
_bstr_t bstrPropName = (*ppmbp)->pszPropName;
|
||
|
|
||
|
PutProperty(spObj, bstrPropName, &vt, bInherited, bDefault);
|
||
|
|
||
|
vt.Clear();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
io_pMetabase->CacheFree();
|
||
|
io_pMetabase->CloseKey(hKey);
|
||
|
hKey = NULL;
|
||
|
|
||
|
//
|
||
|
// Set qualifiers
|
||
|
//
|
||
|
LPCWSTR awszNames[2] = { g_wszInstanceName, g_wszInstanceExists };
|
||
|
VARIANT apvValues[2];
|
||
|
apvValues[0].bstrVal = bstrMbPath;
|
||
|
apvValues[0].vt = VT_BSTR;
|
||
|
apvValues[1].boolVal = vtTrue.boolVal;
|
||
|
apvValues[1].vt = vtTrue.vt;
|
||
|
|
||
|
hr = CUtils::SetQualifiers(spObj, awszNames, apvValues, 2,
|
||
|
WBEM_FLAVOR_FLAG_PROPAGATE_TO_INSTANCE);
|
||
|
THROW_ON_ERROR(hr);
|
||
|
|
||
|
//
|
||
|
// Set out parameters on success
|
||
|
//
|
||
|
*o_ppObj = spObj;
|
||
|
(*o_ppObj)->AddRef();
|
||
|
}
|
||
|
|
||
|
void CInstanceHelper::PutProperty(
|
||
|
IWbemClassObject* i_pInstance,
|
||
|
const BSTR i_bstrPropName,
|
||
|
VARIANT* i_vtPropValue,
|
||
|
BOOL i_bIsInherited,
|
||
|
BOOL i_bIsDefault)
|
||
|
{
|
||
|
DBG_ASSERT(i_pInstance);
|
||
|
DBG_ASSERT(i_bstrPropName);
|
||
|
DBG_ASSERT(i_vtPropValue);
|
||
|
|
||
|
HRESULT hr = WBEM_S_NO_ERROR;
|
||
|
|
||
|
VARIANT vtTrue;
|
||
|
vtTrue.boolVal = VARIANT_TRUE;
|
||
|
vtTrue.vt = VT_BOOL;
|
||
|
|
||
|
//
|
||
|
// TODO: Log error if Put fails.
|
||
|
//
|
||
|
hr = i_pInstance->Put(i_bstrPropName, 0, i_vtPropValue, 0);
|
||
|
if(FAILED(hr))
|
||
|
{
|
||
|
DBGPRINTF((
|
||
|
DBG_CONTEXT,
|
||
|
"The property %ws in class %ws is not in repository\n",
|
||
|
i_bstrPropName,
|
||
|
m_pWmiClass->pszClassName));
|
||
|
}
|
||
|
|
||
|
if(i_bIsInherited && SUCCEEDED(hr))
|
||
|
{
|
||
|
hr = CUtils::SetPropertyQualifiers(
|
||
|
i_pInstance, i_bstrPropName, &g_wszIsInherit, &vtTrue, 1);
|
||
|
THROW_ON_ERROR(hr);
|
||
|
}
|
||
|
else if(i_bIsDefault && SUCCEEDED(hr))
|
||
|
{
|
||
|
hr = CUtils::SetPropertyQualifiers(
|
||
|
i_pInstance, i_bstrPropName, &g_wszIsDefault, &vtTrue, 1);
|
||
|
THROW_ON_ERROR(hr);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
bool CInstanceHelper::CheckForQueryMatch(
|
||
|
const SQL_LEVEL_1_TOKEN* i_pToken,
|
||
|
const VARIANT* i_pvtMatch)
|
||
|
/*++
|
||
|
|
||
|
Synopsis:
|
||
|
It's okay to return true even if there is not a match, but we should
|
||
|
never do the opposite.
|
||
|
|
||
|
Arguments: [i_pToken] -
|
||
|
[i_pvtMatch] -
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
--*/{
|
||
|
DBG_ASSERT(i_pToken);
|
||
|
DBG_ASSERT(i_pvtMatch);
|
||
|
DBG_ASSERT(i_pToken->nTokenType == SQL_LEVEL_1_TOKEN::OP_EXPRESSION);
|
||
|
|
||
|
bool bTypesMatch = false;
|
||
|
|
||
|
|
||
|
//
|
||
|
// Used only for VT_BOOL and VT_I4
|
||
|
//
|
||
|
ULONG ulToken = 0;
|
||
|
ULONG ulMatch = 0;
|
||
|
|
||
|
if( i_pvtMatch->vt == i_pToken->vConstValue.vt )
|
||
|
{
|
||
|
bTypesMatch = true;
|
||
|
}
|
||
|
|
||
|
if(bTypesMatch)
|
||
|
{
|
||
|
switch(i_pvtMatch->vt)
|
||
|
{
|
||
|
case VT_BOOL:
|
||
|
ulMatch = i_pvtMatch->boolVal ? 1 : 0;
|
||
|
ulToken = i_pToken->vConstValue.boolVal ? 1 : 0;
|
||
|
//
|
||
|
// deliberate fall thru
|
||
|
//
|
||
|
case VT_I4:
|
||
|
if(i_pvtMatch->vt == VT_I4)
|
||
|
{
|
||
|
ulMatch = i_pvtMatch->lVal;
|
||
|
ulToken = i_pToken->vConstValue.lVal;
|
||
|
}
|
||
|
switch(i_pToken->nOperator)
|
||
|
{
|
||
|
case SQL_LEVEL_1_TOKEN::OP_EQUAL:
|
||
|
if(ulToken != ulMatch)
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
break;
|
||
|
case SQL_LEVEL_1_TOKEN::OP_NOT_EQUAL:
|
||
|
if(ulToken == ulMatch)
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
break;
|
||
|
case SQL_LEVEL_1_TOKEN::OP_EQUALorGREATERTHAN:
|
||
|
if(ulToken < ulMatch)
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
break;
|
||
|
case SQL_LEVEL_1_TOKEN::OP_EQUALorLESSTHAN:
|
||
|
if(ulToken > ulMatch)
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
break;
|
||
|
case SQL_LEVEL_1_TOKEN::OP_LESSTHAN:
|
||
|
if(ulToken >= ulMatch)
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
break;
|
||
|
case SQL_LEVEL_1_TOKEN::OP_GREATERTHAN:
|
||
|
if(ulToken <= ulMatch)
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
break;
|
||
|
case VT_BSTR:
|
||
|
if(i_pToken->vConstValue.bstrVal && i_pvtMatch->bstrVal)
|
||
|
{
|
||
|
switch(i_pToken->nOperator)
|
||
|
{
|
||
|
case SQL_LEVEL_1_TOKEN::OP_EQUAL:
|
||
|
if(_wcsicmp(i_pToken->vConstValue.bstrVal, i_pvtMatch->bstrVal) != 0)
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
break;
|
||
|
case SQL_LEVEL_1_TOKEN::OP_NOT_EQUAL:
|
||
|
if(_wcsicmp(i_pToken->vConstValue.bstrVal, i_pvtMatch->bstrVal) == 0)
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|