2025-04-27 07:49:33 -04:00

2843 lines
90 KiB
C++

//***************************************************************************
//
// Copyright (c) 1997-1999 Microsoft Corporation
//
// PARSE.CPP
//
// rajeshr 3/25/2000 Created.
//
// Contains the class that interacts with WMI to satisfy XML/HTTP requests
//
//***************************************************************************
#include <windows.h>
#include <stdio.h>
#include <initguid.h>
#include <objbase.h>
#include <wbemcli.h>
#include <wmiutils.h>
#include <genlex.h>
#include <opathlex.h>
#include <objpath.h>
#include <cominit.h>
#include <httpext.h>
#include <msxml.h>
#include "provtempl.h"
#include "common.h"
#include "wmixmlop.h"
#include "wmixmlst.h"
#include "concache.h"
#include "wmiconv.h"
#include "xml2wmi.h"
#include "wmixmlt.h"
#include "request.h"
#include "whistler.h"
#include "strings.h"
#include "xmlhelp.h"
#include "parse.h"
// Strings for queries
#define WMIXMLT_Q L"select __CLASS,__GENUS,__SUPERCLASS, __PATH, __RELPATH, "
static WCHAR *BuildPropertyList (DWORD dwNumProperties, BSTR *pPropertyArray);
static BSTR FormatAssociatorsQuery(
BSTR strObjectPath,
BSTR strAssocClass,
BSTR strResultClass,
BSTR strResultRole,
BSTR strRole,
VARIANT_BOOL bClassesOnly,
VARIANT_BOOL bSchemaOnly,
BSTR strRequiredAssocQualifier,
BSTR strRequiredQualifier
);
static BSTR FormatReferencesQuery(
BSTR strObjectPath,
BSTR strResultClass,
BSTR strRole,
VARIANT_BOOL bClassesOnly,
VARIANT_BOOL bSchemaOnly,
BSTR strRequiredQualifier
);
// Required for the Query parser
static ULONG uFeatures[] =
{
WMIQ_LF1_BASIC_SELECT,
WMIQ_LF2_CLASS_NAME_IN_QUERY
};
// Strings for association and reference queries
#define WMIXML_QUERY_ASSOCOF OLESTR("associators of ")
#define WMIXML_QUERY_OPENBRACE OLESTR("{")
#define WMIXML_QUERY_CLOSEBRACE OLESTR("}")
#define WMIXML_QUERY_WHERE OLESTR(" where ")
#define WMIXML_QUERY_ASSOCCLASS OLESTR(" AssocClass ")
#define WMIXML_QUERY_EQUALS OLESTR("=")
#define WMIXML_QUERY_CLASSDEFS OLESTR(" ClassDefsOnly ")
#define WMIXML_QUERY_REQASSOCQ OLESTR(" RequiredAssocQualifier ")
#define WMIXML_QUERY_REQQUAL OLESTR(" RequiredQualifier ")
#define WMIXML_QUERY_RESCLASS OLESTR(" ResultClass ")
#define WMIXML_QUERY_RESROLE OLESTR(" ResultRole ")
#define WMIXML_QUERY_ROLE OLESTR(" Role ")
#define WMIXML_QUERY_SCHEMAONLY OLESTR(" SchemaOnly ")
#define WMIXML_QUERY_REFOF OLESTR("references of ")
//***************************************************************************
//
// CXMLTranslator::CXMLTranslator
//
// DESCRIPTION:
//
// Constructor.
//
//***************************************************************************
CXMLTranslator::CXMLTranslator(IXMLDOMNode *pContext, WMI_XML_HTTP_VERSION iHttpVersion, IStream *pPrefixStream, IStream *pSuffixStream)
{
m_iHttpVersion = iHttpVersion;
if(m_pContext = pContext)
m_pContext->AddRef();
if(m_pPrefixStream = pPrefixStream)
m_pPrefixStream->AddRef();
if(m_pSuffixStream = pSuffixStream)
m_pSuffixStream->AddRef();
}
//***************************************************************************
//
// CXMLTranslator::~CXMLTranslator
//
// DESCRIPTION:
//
// Destructor.
//
//***************************************************************************
CXMLTranslator::~CXMLTranslator(void)
{
if(m_pPrefixStream)
m_pPrefixStream->Release();
if(m_pSuffixStream)
m_pSuffixStream->Release();
if(m_pContext)
m_pContext->Release();
}
//***************************************************************************
//
// SCODE CXMLTranslator::GetObject
//
// DESCRIPTION:
//
// Transforms a single WBEM object into its equivalent XML representation
//
// PARAMETERS:
//
// pszNamespacePath The namespace path in which the object resides
// pszObjectPath The relative (model) path of the object within
// that namespace
// pXML On successful return addresses the XML document.
// The caller is responsible for freeing this BSTR
// using SysFreeString.
//
// RETURN VALUES:
//
// WBEM_S_NO_ERROR success, XML document is addressed by pXML
// WBEM_E_INVALID_PARAMETER bad input parameters
// WBEM_E_FAILED otherwise
//
// Other WBEM error codes may be returned by ConnectServer etc., in which
// case these are passed on to the caller.
//
//***************************************************************************
HRESULT CXMLTranslator::GetObject (
BSTR pszNamespacePath,
BSTR pszObjectPath,
DWORD dwNumProperties,
BSTR *pPropertyArray,
LPEXTENSION_CONTROL_BLOCK pECB,
IWbemContext *pFlagsContext
)
{
HRESULT hr = WBEM_E_FAILED;
if (NULL == pszObjectPath)
{
hr = WBEM_E_INVALID_PARAMETER;
}
else
{
// Connect to the requested namespace
IWbemServices *pService = NULL;
if (SUCCEEDED (hr = m_connectionCache.GetConnectionByPath (pszNamespacePath, &pService)))
{
// Create an IWbemContext Object if the client is WMI
IWbemContext *pContext = NULL;
if(m_pContext)
hr = CXmlToWmi::MapContextObject(m_pContext, &pContext);
if(SUCCEEDED(hr))
{
// Get the requested object
IWbemClassObject *pObject = NULL;
// Check to see if this version of WMI supports the WBEM_FLAG_USE_AMENDED_QUALIFIERS flag
// Otherwise, make a best effort call with no flags.
// We need this to get the properties that have the "amended" qualifier on them
if(WBEM_E_INVALID_PARAMETER == (hr = pService->GetObject (pszObjectPath, WBEM_FLAG_USE_AMENDED_QUALIFIERS, pContext, &pObject, NULL)))
hr = pService->GetObject (pszObjectPath, 0, pContext, &pObject, NULL);
if (WBEM_S_NO_ERROR == hr)
{
switch(m_iHttpVersion)
{
// We write everything on to the prefix stream since there is no
// chunked encoding in HTTP 1.0
case WMI_XML_HTTP_VERSION_1_0:
{
// Create the convertor
IWbemXMLConvertor *pConvertor = NULL;
if(SUCCEEDED(hr = CreateXMLTranslator(&pConvertor)))
{
// Now do the translation
if(SUCCEEDED(hr = SetI4ContextValue(pFlagsContext, L"PathLevel", 0)))
{
// Write an IRETURNVALUE to the Prefix Stream
WRITEBSTR(m_pPrefixStream, L"<IRETURNVALUE>");
pConvertor->MapObjectToXML(pObject, pPropertyArray, dwNumProperties, pFlagsContext, m_pPrefixStream, NULL);
WRITEBSTR(m_pPrefixStream, L"</IRETURNVALUE>");
}
pConvertor->Release();
}
}
break;
case WMI_XML_HTTP_VERSION_1_1:
{
// Create a stream
// The reason we create a new stream instead of writing into m_pPrefixStream
// is that we dont know if the call to MapObjectToXML will be successful
// In the case it isnt, then we cannot write the IRETURNVALUE tag
// In the case it is, we need to write the IRETURNVALUE tag before
// the encoding of the object
IStream *pStream = NULL;
if (SUCCEEDED(hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream)))
{
// Create the convertor
IWbemXMLConvertor *pConvertor = NULL;
if(SUCCEEDED(hr = CreateXMLTranslator(&pConvertor)))
{
// Now do the translation
if(SUCCEEDED(hr = SetI4ContextValue(pFlagsContext, L"PathLevel", 0)))
{
if (SUCCEEDED(hr = pConvertor->MapObjectToXML(pObject, pPropertyArray, dwNumProperties, pFlagsContext, pStream, NULL)))
{
// First Write an IRETURNVALUE to the Prefix Stream
WRITEBSTR(m_pPrefixStream, L"<IRETURNVALUE>");
WRITEBSTR(pStream, L"</IRETURNVALUE>");
// Write the translation to the IIS Socket
SavePrefixAndBodyToIISSocket(m_pPrefixStream, pStream, pECB, m_iHttpVersion == WMI_XML_HTTP_VERSION_1_1);
}
}
pConvertor->Release();
}
pStream->Release ();
}
}
break;
}
pObject->Release ();
}
}
// Release the IWbemContext, if any
if(pContext)
pContext->Release();
pService->Release();
}
}
// In case of HTTP 1.1, We have to ensure that we write thr contents of m_pPrefixStream to the socket irrespective of whether the call failed or not
if(FAILED(hr) && m_iHttpVersion == WMI_XML_HTTP_VERSION_1_1)
SavePrefixAndBodyToIISSocket(m_pPrefixStream, NULL, pECB, TRUE);
return hr;
}
//***************************************************************************
//
// SCODE CXMLTranslator::GetProperty
//
// DESCRIPTION:
//
// Transforms a single WBEM Property value into its equivalent XML representation
//
// PARAMETERS:
//
// pszNamespacePath The namespace path in which the object resides
// pszObjectPath The relative (model) path of the object within
// that namespace
// pszPropertyName Name of the property whose value is requested
// pXML On successful return addresses the XML document.
// The caller is responsible for freeing this BSTR
// using SysFreeString.
//
// RETURN VALUES:
//
// WBEM_S_NO_ERROR success, XML document is addressed by pXML
// WBEM_E_INVALID_PARAMETER bad input parameters
// WBEM_E_FAILED otherwise
//
// Other WBEM error codes may be returned by ConnectServer etc., in which
// case these are passed on to the caller.
//
//***************************************************************************
HRESULT CXMLTranslator::GetProperty (
BSTR pszNamespacePath,
BSTR pszObjectPath,
BSTR pszPropertyName,
LPEXTENSION_CONTROL_BLOCK pECB,
IWbemContext *pFlagsContext
)
{
HRESULT hr = WBEM_E_FAILED;
if ((NULL == pszObjectPath) || (NULL == pszPropertyName))
{
hr = WBEM_E_INVALID_PARAMETER;
}
else
{
// Connect to the requested namespace
IWbemServices *pService = NULL;
if (SUCCEEDED (hr = m_connectionCache.GetConnectionByPath (pszNamespacePath, &pService)))
{
// Create an IWbemContext Object if the client is WMI
IWbemContext *pContext = NULL;
if(m_pContext)
hr = CXmlToWmi::MapContextObject(m_pContext, &pContext);
if(SUCCEEDED(hr))
{
// Dont create a new context if we already have one
if(pContext || (!pContext && SUCCEEDED(hr = CoCreateInstance (CLSID_WbemContext, NULL, CLSCTX_INPROC_SERVER,
IID_IWbemContext, (void**) &pContext))) )
{
// Add the per-property GET information into the context
VARIANT var;
VariantInit (&var);
var.vt = VT_BOOL;
var.boolVal = VARIANT_TRUE;
HRESULT hr2 = pContext->SetValue (L"__GET_EXTENSIONS", 0, &var);
VariantClear (&var);
SAFEARRAYBOUND rgsabound [1];
rgsabound [0].lLbound = 0;
rgsabound [0].cElements = 1;
SAFEARRAY *pArray = SafeArrayCreate (VT_BSTR, 1, rgsabound);
long ix = 0;
hr2 = SafeArrayPutElement (pArray, &ix, pszPropertyName);
var.vt = VT_ARRAY|VT_BSTR;
var.parray = pArray;
hr2 = pContext->SetValue (L"__GET_EXT_PROPERTIES", 0, &var);
VariantClear (&var);
// Get the requested object
IWbemClassObject *pObject = NULL;
// Check to see if this version of WMI supports the WBEM_FLAG_USE_AMENDED_QUALIFIERS flag
// Otherwise, make a best effort call with no flags.
// We need this to get the properties that have the "amended" qualifier on them
if(WBEM_E_INVALID_PARAMETER == (hr = pService->GetObject (pszObjectPath, WBEM_FLAG_USE_AMENDED_QUALIFIERS, pContext, &pObject, NULL)))
hr = pService->GetObject (pszObjectPath, 0, pContext, &pObject, NULL);
if (WBEM_S_NO_ERROR == hr)
{
switch(m_iHttpVersion)
{
// We write everything on to the prefix stream since there is no
// chunked encoding in HTTP 1.0
case WMI_XML_HTTP_VERSION_1_0:
{
// Create the convertor
IWbemXMLConvertor *pConvertor = NULL;
if(SUCCEEDED(hr = CreateXMLTranslator(&pConvertor)))
{
// First Write an IRETURNVALUE to the Prefix Stream
WRITEBSTR(m_pPrefixStream, L"<IRETURNVALUE>");
// Now do the translation
hr = pConvertor->MapPropertyToXML (pObject, pszPropertyName, pFlagsContext, m_pPrefixStream);
WRITEBSTR(m_pPrefixStream, L"</IRETURNVALUE>");
pConvertor->Release();
}
}
break;
case WMI_XML_HTTP_VERSION_1_1:
{
// Create a stream
IStream *pStream = NULL;
if (SUCCEEDED(hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream)))
{
// Create the convertor
IWbemXMLConvertor *pConvertor = NULL;
if(SUCCEEDED(hr = CreateXMLTranslator(&pConvertor)))
{
// Now do the translation
if (SUCCEEDED(hr = pConvertor->MapPropertyToXML (pObject, pszPropertyName, pFlagsContext, pStream)))
{
// First Write an IRETURNVALUE to the Prefix Stream
WRITEBSTR(m_pPrefixStream, L"<IRETURNVALUE>");
WRITEBSTR(pStream, L"</IRETURNVALUE>");
// Write the translation to the IIS Socket
SavePrefixAndBodyToIISSocket(m_pPrefixStream, pStream, pECB, m_iHttpVersion == WMI_XML_HTTP_VERSION_1_1);
}
pConvertor->Release();
}
pStream->Release ();
}
}
break;
}
pObject->Release ();
}
}
}
// Release the IWbemContext object, if any
if(pContext)
pContext->Release();
pService->Release();
}
}
// In case of HTTP 1.1, We have to ensure that we write thr contents of m_pPrefixStream to the socket irrespective of whether the call failed or not
if(FAILED(hr) && m_iHttpVersion == WMI_XML_HTTP_VERSION_1_1)
SavePrefixAndBodyToIISSocket(m_pPrefixStream, NULL, pECB, TRUE);
return hr;
}
//***************************************************************************
//
// SCODE CXMLTranslator::SetProperty
//
// DESCRIPTION:
//
// Updates a single WBEM Property value
//
// PARAMETERS:
//
// pszNamespacePath The namespace path in which the object resides
// pszObjectPath The relative (model) path of the object within
// that namespace
// pszPropertyName Name of the property whose value is requested
// pszPropertyValue The proposed value as an XML string
//
// RETURN VALUES:
//
// WBEM_S_NO_ERROR success, XML document is addressed by pXML
// WBEM_E_INVALID_PARAMETER bad input parameters
// WBEM_E_FAILED otherwise
//
// Other WBEM error codes may be returned by ConnectServer etc., in which
// case these are passed on to the caller.
//
//***************************************************************************
HRESULT CXMLTranslator::SetProperty (
BSTR pszNamespacePath,
BSTR pszObjectPath,
BSTR pszPropertyName,
IXMLDOMNode *pPropertyValue,
LPEXTENSION_CONTROL_BLOCK pECB,
IWbemContext *pFlagsContext
)
{
// In case of HTTP 1.1, We have to ensure that we write thr contents of m_pPrefixStream to the socket irrespective of whether the call failed or not
if(m_iHttpVersion == WMI_XML_HTTP_VERSION_1_1)
SavePrefixAndBodyToIISSocket(m_pPrefixStream, NULL, pECB, TRUE);
HRESULT hr = WBEM_E_FAILED;
if ((NULL == pszObjectPath) || (NULL == pszPropertyName))
{
hr = WBEM_E_INVALID_PARAMETER;
}
else
{
// Connect to the requested namespace
IWbemServices *pService = NULL;
if (SUCCEEDED (hr = m_connectionCache.GetConnectionByPath (pszNamespacePath, &pService)))
{
// Create an IWbemContext Object if the client is WMI
IWbemContext *pContext = NULL;
if(m_pContext)
hr = CXmlToWmi::MapContextObject(m_pContext, &pContext);
if(SUCCEEDED(hr))
{
// Get the requested object first
IWbemClassObject *pObject = NULL;
if (WBEM_S_NO_ERROR == (hr = pService->GetObject (pszObjectPath, 0, NULL, &pObject, NULL)))
{
// Map the property value to its VARIANT equivalent and set in the
// object
VARIANT vvar;
VariantInit (&vvar);
CIMTYPE cimtype;
long flavor;
if (SUCCEEDED (hr = pObject->Get (pszPropertyName, 0, &vvar, &cimtype, &flavor)))
{
// Got the property - now map the new value and attempt to set it
CXmlToWmi xmlToWmi;
if(SUCCEEDED(hr = xmlToWmi.Initialize(pPropertyValue)))
{
if (SUCCEEDED (hr = xmlToWmi.MapPropertyValue (vvar, cimtype)))
{
if (SUCCEEDED (hr = pObject->Put (pszPropertyName, 0, &vvar, 0)))
{
// Set the value OK - now do a per-property put to commit the change
if (pContext || (!pContext && SUCCEEDED(hr = CoCreateInstance (CLSID_WbemContext, NULL, CLSCTX_INPROC_SERVER,
IID_IWbemContext, (void**) &pContext))) )
{
// Add the per-property PUT information into the context
VARIANT cvar;
VariantInit (&cvar);
cvar.vt = VT_BOOL;
cvar.boolVal = VARIANT_TRUE;
HRESULT hr2 = pContext->SetValue (L"__PUT_EXTENSIONS", 0, &cvar);
VariantClear (&cvar);
SAFEARRAYBOUND rgsabound [1];
rgsabound [0].lLbound = 0;
rgsabound [0].cElements = 1;
SAFEARRAY *pArray = SafeArrayCreate (VT_BSTR, 1, rgsabound);
long ix = 0;
hr2 = SafeArrayPutElement (pArray, &ix, pszPropertyName);
cvar.vt = VT_ARRAY|VT_BSTR;
cvar.parray = pArray;
hr2 = pContext->SetValue (L"__PUT_EXT_PROPERTIES", 0, &cvar);
VariantClear (&cvar);
// Set the instance - if we get WBEM_E_PROVIDER_NOT_CAPABLE,
// roll back to a simple put with no context
hr = pService->PutInstance (pObject, WBEM_FLAG_UPDATE_ONLY,
pContext, NULL);
if (WBEM_E_PROVIDER_NOT_CAPABLE == hr)
hr = pService->PutInstance (pObject, WBEM_FLAG_UPDATE_ONLY,
NULL, NULL);
}
}
}
}
}
VariantClear (&vvar);
pObject->Release ();
}
}
// Release the IWbemContext object, if any
if(pContext)
pContext->Release();
pService->Release();
}
}
return hr;
}
//***************************************************************************
//
// SCODE CXMLTranslator::CreateClass
//
// DESCRIPTION:
//
// Creates a new WMI class or modifies an existing one
//
// PARAMETERS:
//
// pszNamespacePath The namespace path in which the object resides
// pClass The new class definition in XML format
// bIsModify Whether this is a modify operation
//
// RETURN VALUES:
//
// WBEM_S_NO_ERROR success, XML document is addressed by pXML
// WBEM_E_INVALID_PARAMETER bad input parameters
// WBEM_E_FAILED otherwise
//
// Other WBEM error codes may be returned by ConnectServer etc., in which
// case these are passed on to the caller.
//
//***************************************************************************
HRESULT CXMLTranslator::CreateClass (
BSTR pszNamespacePath,
IXMLDOMNode *pClass,
BOOL bIsModify,
LPEXTENSION_CONTROL_BLOCK pECB,
IWbemContext *pFlagsContext,
LONG lFlags)
{
// In case of HTTP 1.1, We have to ensure that we write thr contents of m_pPrefixStream to the socket irrespective of whether the call failed or not
if(m_iHttpVersion == WMI_XML_HTTP_VERSION_1_1)
SavePrefixAndBodyToIISSocket(m_pPrefixStream, NULL, pECB, TRUE);
HRESULT hr = WBEM_E_FAILED;
if ((NULL == pszNamespacePath) || (NULL == pClass))
{
hr = WBEM_E_INVALID_PARAMETER;
}
else
{
// Connect to the requested namespace
IWbemServices *pService = NULL;
if (SUCCEEDED (hr = m_connectionCache.GetConnectionByPath (pszNamespacePath, &pService)))
{
// Create an IWbemContext Object if the client is WMI
IWbemContext *pContext = NULL;
if(m_pContext)
hr = CXmlToWmi::MapContextObject(m_pContext, &pContext);
if(SUCCEEDED(hr))
{
if (!bIsModify)
{
// Get the base object first; need to know if this is derived or not
IWbemClassObject *pObject = NULL;
// Should have a CLASS element - does it have a SUPERCLASS attribute?
BSTR strSuperClass = NULL;
GetBstrAttribute (pClass, SUPERCLASS_ATTRIBUTE, &strSuperClass);
if (WBEM_S_NO_ERROR == (hr = pService->GetObject (strSuperClass, 0, pContext, &pObject, NULL)))
{
// Got the underlying class - now map the new value and attempt to set it
if (strSuperClass && (0 < wcslen (strSuperClass)))
{
IWbemClassObject *pSubClass = NULL;
if (SUCCEEDED(hr = pObject->SpawnDerivedClass (0, &pSubClass)))
{
CXmlToWmi xmlToWmi;
if(SUCCEEDED(hr = xmlToWmi.Initialize(pClass, pService, pSubClass)))
{
if (SUCCEEDED (hr = xmlToWmi.MapClass ()))
hr = pService->PutClass (pSubClass, WBEM_FLAG_CREATE_OR_UPDATE | lFlags, pContext, NULL);
}
pSubClass->Release ();
}
}
else
{
CXmlToWmi xmlToWmi;
if(SUCCEEDED(hr = xmlToWmi.Initialize(pClass, pService, pObject)))
{
if (SUCCEEDED(hr = xmlToWmi.MapClass ()))
hr = pService->PutClass (pObject, WBEM_FLAG_CREATE_OR_UPDATE|lFlags, pContext, NULL);
}
}
pObject->Release ();
}
SysFreeString (strSuperClass);
}
else
{
// Get the existing class definition first
IWbemClassObject *pObject = NULL;
// Should have a CLASS element - does it have a NAME attribute?
BSTR strClass = NULL;
GetBstrAttribute (pClass, NAME_ATTRIBUTE, &strClass);
if (WBEM_S_NO_ERROR == (hr = pService->GetObject (strClass, 0, pContext, &pObject, NULL)))
{
CXmlToWmi xmlToWmi;
if(SUCCEEDED(hr = xmlToWmi.Initialize(pClass, pService, pObject)))
{
if (SUCCEEDED(hr = xmlToWmi.MapClass (TRUE)))
hr = pService->PutClass (pObject, WBEM_FLAG_UPDATE_ONLY|lFlags, NULL, NULL);
}
pObject->Release ();
}
SysFreeString (strClass);
}
}
// Release the IWbemContext object, if any
if(pContext)
pContext->Release();
pService->Release();
}
}
return hr;
}
//***************************************************************************
//
// SCODE CXMLTranslator::CreateInstance
//
// DESCRIPTION:
//
// Creates a new WMI instance
//
// PARAMETERS:
//
// pszNamespacePath The namespace path in which the object resides
// pInstance The new instance definition in XML format
//
// RETURN VALUES:
//
// WBEM_S_NO_ERROR success, XML document is addressed by pXML
// WBEM_E_INVALID_PARAMETER bad input parameters
// WBEM_E_FAILED otherwise
//
// Other WBEM error codes may be returned by ConnectServer etc., in which
// case these are passed on to the caller.
//
//***************************************************************************
HRESULT CXMLTranslator::CreateInstance (
BSTR pszNamespacePath,
IXMLDOMNode *pInstance,
LPEXTENSION_CONTROL_BLOCK pECB,
IWbemContext *pFlagsContext,
LONG lFlags)
{
HRESULT hr = WBEM_E_FAILED;
if ((NULL == pszNamespacePath) || (NULL == pInstance))
{
hr = WBEM_E_INVALID_PARAMETER;
}
else
{
// Connect to the requested namespace
IWbemServices *pService = NULL;
if (SUCCEEDED (hr = m_connectionCache.GetConnectionByPath (pszNamespacePath, &pService)))
{
// Create an IWbemContext Object if the client is WMI
IWbemContext *pContext = NULL;
if(m_pContext)
hr = CXmlToWmi::MapContextObject(m_pContext, &pContext);
if(SUCCEEDED(hr))
{
IWbemClassObject *pObject = NULL;
// Should have a CLASSNAME attribute
BSTR strClassName = NULL;
GetBstrAttribute (pInstance, CLASS_NAME_ATTRIBUTE, &strClassName);
if (strClassName && (0 < wcslen (strClassName)) &&
WBEM_S_NO_ERROR == (hr = pService->GetObject (strClassName, 0, NULL, &pObject, NULL)))
{
// Got the underlying class - now map the new value and attempt to set it
IWbemClassObject *pNewInstance = NULL;
if (SUCCEEDED(hr = pObject->SpawnInstance (0, &pNewInstance)))
{
CXmlToWmi xmlToWmi;
if(SUCCEEDED(hr = xmlToWmi.Initialize(pInstance, pService, pNewInstance)))
{
if (SUCCEEDED (hr = xmlToWmi.MapInstance ()))
{
IWbemCallResult *pResult = NULL;
// We need to make this a semi-sync call so that we can get
// the object name of the create object
if (SUCCEEDED(hr = pService->PutInstance
(pNewInstance, WBEM_FLAG_CREATE_ONLY|WBEM_FLAG_RETURN_IMMEDIATELY|lFlags, pContext, &pResult)) && pResult)
{
HRESULT hCallResult = S_OK;
if (SUCCEEDED(hr = pResult->GetCallStatus (INFINITE, &hCallResult)))
{
if(SUCCEEDED(hCallResult))
{
// Now get the relpath string from the call result
hr = WBEM_E_FAILED;
BSTR resultString = NULL;
if (SUCCEEDED(hr = pResult->GetResultString (INFINITE, &resultString)))
{
switch(m_iHttpVersion)
{
// We write everything on to the prefix stream since there is no
// chunked encoding in HTTP 1.0
case WMI_XML_HTTP_VERSION_1_0:
{
// Create the convertor
IWbemXMLConvertor *pConvertor = NULL;
if(SUCCEEDED(hr = CreateXMLTranslator(&pConvertor)))
{
// First Write an IRETURNVALUE to the Prefix Stream
WRITEBSTR(m_pPrefixStream, L"<IRETURNVALUE>");
// Now do the translation
hr = pConvertor->MapInstanceNameToXML(resultString, pFlagsContext, m_pPrefixStream);
WRITEBSTR(m_pPrefixStream, L"</IRETURNVALUE>");
pConvertor->Release();
}
}
break;
case WMI_XML_HTTP_VERSION_1_1:
{
// Create a stream
IStream *pStream = NULL;
if (SUCCEEDED(hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream)))
{
// Create the convertor
IWbemXMLConvertor *pConvertor = NULL;
if(SUCCEEDED(hr = CreateXMLTranslator(&pConvertor)))
{
// Now do the translation
if (SUCCEEDED(hr = pConvertor->MapInstanceNameToXML(resultString, pFlagsContext, pStream)))
{
// First Write an IRETURNVALUE to the Prefix Stream
WRITEBSTR(m_pPrefixStream, L"<IRETURNVALUE>");
WRITEBSTR(pStream, L"</IRETURNVALUE>");
// Write the translation to the IIS Socket
SavePrefixAndBodyToIISSocket(m_pPrefixStream, pStream, pECB, m_iHttpVersion == WMI_XML_HTTP_VERSION_1_1);
}
pConvertor->Release();
}
pStream->Release ();
}
}
break;
}
SysFreeString (resultString);
}
}
else
hr = hCallResult;
}
pResult->Release ();
}
}
}
pNewInstance->Release ();
}
pObject->Release ();
}
SysFreeString (strClassName);
}
// Release the IWbemContext object, if any
if(pContext)
pContext->Release();
pService->Release();
}
}
// In case of HTTP 1.1, We have to ensure that we write thr contents of m_pPrefixStream to the socket irrespective of whether the call failed or not
if(FAILED(hr) && m_iHttpVersion == WMI_XML_HTTP_VERSION_1_1)
SavePrefixAndBodyToIISSocket(m_pPrefixStream, NULL, pECB, TRUE);
return hr;
}
//***************************************************************************
//
// SCODE CXMLTranslator::ModifyInstance
//
// DESCRIPTION:
//
// Modifies an existing WMI instance
//
// PARAMETERS:
//
// pszNamespacePath The namespace path in which the object resides
// pInstance The new instance definition in XML format
// pszInstancePath The instance path
//
// RETURN VALUES:
//
// WBEM_S_NO_ERROR success, XML document is addressed by pXML
// WBEM_E_INVALID_PARAMETER bad input parameters
// WBEM_E_FAILED otherwise
//
// Other WBEM error codes may be returned by ConnectServer etc., in which
// case these are passed on to the caller.
//
//***************************************************************************
HRESULT CXMLTranslator::ModifyInstance (
BSTR pszNamespacePath,
IXMLDOMNode *pInstance,
BSTR pszInstancePath,
LPEXTENSION_CONTROL_BLOCK pECB,
IWbemContext *pFlagsContext,
LONG lFlags
)
{
// In case of HTTP 1.1, We have to ensure that we write thr contents of m_pPrefixStream to the socket irrespective of whether the call failed or not
if(m_iHttpVersion == WMI_XML_HTTP_VERSION_1_1)
SavePrefixAndBodyToIISSocket(m_pPrefixStream, NULL, pECB, TRUE);
HRESULT hr = WBEM_E_FAILED;
if ((NULL == pszInstancePath) || (NULL == pszNamespacePath) || (NULL == pInstance))
{
hr = WBEM_E_INVALID_PARAMETER;
}
else
{
// Connect to the requested namespace
IWbemServices *pService = NULL;
if (SUCCEEDED (hr = m_connectionCache.GetConnectionByPath (pszNamespacePath, &pService)))
{
// Create an IWbemContext Object if the client is WMI
IWbemContext *pContext = NULL;
if(m_pContext)
hr = CXmlToWmi::MapContextObject(m_pContext, &pContext);
if(SUCCEEDED(hr))
{
IWbemClassObject *pCurInstance = NULL;
// Get the instance (MUST exist)
if (WBEM_S_NO_ERROR == (hr = pService->GetObject (pszInstancePath, 0, NULL, &pCurInstance, NULL)))
{
CXmlToWmi xmlToWmi;
if(SUCCEEDED(hr = xmlToWmi.Initialize(pInstance, pService, pCurInstance)))
{
if (SUCCEEDED (hr = xmlToWmi.MapInstance (TRUE)))
hr = pService->PutInstance (pCurInstance, WBEM_FLAG_UPDATE_ONLY|lFlags, pContext, NULL);
}
pCurInstance->Release ();
}
}
// Release the IWbemContext object, if any
if(pContext)
pContext->Release();
pService->Release();
}
}
return hr;
}
//***************************************************************************
//
// SCODE CXMLTranslator::DeleteObject
//
// DESCRIPTION:
//
// Delete a class or instance
//
// PARAMETERS:
//
// pszNamespacePath The namespace path in which the object resides
// pszObjectPath The relative (model) path of the object within
// that namespace
// bIsClass Whether this is a class or instance
//
// RETURN VALUES:
//
// WBEM_S_NO_ERROR success, XML document is addressed by pXML
// WBEM_E_INVALID_PARAMETER bad input parameters
// WBEM_E_FAILED otherwise
//
// Other WBEM error codes may be returned by ConnectServer etc., in which
// case these are passed on to the caller.
//
//***************************************************************************
HRESULT CXMLTranslator::DeleteObject (
BSTR pszNamespacePath,
BSTR pszObjectPath,
BOOL bIsClass,
LPEXTENSION_CONTROL_BLOCK pECB,
IWbemContext *pFlagsContext
)
{
// In case of HTTP 1.1, We have to ensure that we write thr contents of m_pPrefixStream to the socket irrespective of whether the call failed or not
if(m_iHttpVersion == WMI_XML_HTTP_VERSION_1_1)
SavePrefixAndBodyToIISSocket(m_pPrefixStream, NULL, pECB, TRUE);
HRESULT hr = WBEM_E_FAILED;
if (NULL == pszObjectPath)
{
hr = WBEM_E_INVALID_PARAMETER;
}
else
{
// Connect to the requested namespace
IWbemServices *pService = NULL;
if (SUCCEEDED (hr = m_connectionCache.GetConnectionByPath (pszNamespacePath, &pService)))
{
// Create an IWbemContext Object if the client is WMI
IWbemContext *pContext = NULL;
if(m_pContext)
hr = CXmlToWmi::MapContextObject(m_pContext, &pContext);
if(SUCCEEDED(hr))
{
// Delete the requested object
hr = (bIsClass) ? pService->DeleteClass (pszObjectPath, 0, pContext, NULL):
pService->DeleteInstance (pszObjectPath, 0, pContext, NULL);
}
// Release the IWbemContext object, if any
if(pContext)
pContext->Release();
pService->Release();
}
}
return hr;
}
//***************************************************************************
//
// SCODE CXMLTranslator::ExecuteQuery
//
// DESCRIPTION:
//
// Transforms the query result set nto its equivalent XML representation
//
// PARAMETERS:
//
// pszNamespacePath The namespace path in which the object resides.
// pszQueryLanguage The query language used
// pszQueryString The query to execute within that namespace.
// pXML On successful return addresses the XML document.
// The caller is responsible for freeing this BSTR
// using SysFreeString.
//
// RETURN VALUES:
//
// WBEM_S_NO_ERROR success, XML document is addressed by pXML
// WBEM_E_INVALID_PARAMETER bad input parameters
// WBEM_E_FAILED otherwise
//
// Other WBEM error codes may be returned by ConnectServer etc., in which
// case these are passed on to the caller.
//
//***************************************************************************
HRESULT CXMLTranslator::ExecuteQuery (
BSTR pszNamespacePath,
BSTR pszQueryLanguage,
BSTR pszQueryString,
LPEXTENSION_CONTROL_BLOCK pECB,
IWbemContext *pFlagsContext
)
{
HRESULT hr = WBEM_E_FAILED;
if ((NULL == pszNamespacePath) || (NULL == pszQueryString))
{
hr = WBEM_E_INVALID_PARAMETER;
}
else
{
// Connect to the requested namespace
IWbemServices *pService = NULL;
if (SUCCEEDED (hr = m_connectionCache.GetConnectionByPath (pszNamespacePath, &pService)))
{
// Create an IWbemContext Object if the client is WMI
IWbemContext *pContext = NULL;
if(m_pContext)
hr = CXmlToWmi::MapContextObject(m_pContext, &pContext);
if(SUCCEEDED(hr))
{
// Transform the query to include suitable system properties
BOOL bMustFreeQueryString = TransformQuery (&pszQueryString);
// Perform the query
IEnumWbemClassObject *pEnum = NULL;
// Check to see if this version of WMI supports the WBEM_FLAG_USE_AMENDED_QUALIFIERS flag
// Otherwise, make a best effort call with no flags.
// We need this to get the properties that have the "amended" qualifier on them
long lFlags = WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY;
if(WBEM_E_INVALID_PARAMETER == (hr = pService->ExecQuery (pszQueryLanguage, pszQueryString, lFlags | WBEM_FLAG_USE_AMENDED_QUALIFIERS, pContext, &pEnum)))
hr = pService->ExecQuery (pszQueryLanguage, pszQueryString, lFlags, pContext, &pEnum);
if (WBEM_S_NO_ERROR == hr)
{
// Ensure we have impersonation enabled
DWORD dwAuthnLevel, dwImpLevel;
GetAuthImp (pEnum, &dwAuthnLevel, &dwImpLevel);
if (RPC_C_IMP_LEVEL_IMPERSONATE != dwImpLevel)
SetInterfaceSecurity (pEnum, NULL, NULL, NULL, dwAuthnLevel, RPC_C_IMP_LEVEL_IMPERSONATE, EOAC_STATIC_CLOAKING);
switch(m_iHttpVersion)
{
// We write everything on to the prefix stream since there is no
// chunked encoding in HTTP 1.0
case WMI_XML_HTTP_VERSION_1_0:
{
// First Write an IRETURNVALUE to the Prefix Stream
WRITEBSTR(m_pPrefixStream, L"<IRETURNVALUE>");
MapEnum (pEnum, 3, 0, NULL, NULL, pECB, pFlagsContext, FALSE, m_pPrefixStream);
WRITEBSTR(m_pPrefixStream, L"</IRETURNVALUE>");
}
break;
case WMI_XML_HTTP_VERSION_1_1:
{
// First Write an IRETURNVALUE to the Prefix Stream
WRITEBSTR(m_pPrefixStream, L"<IRETURNVALUE>");
SaveStreamToIISSocket(m_pPrefixStream, pECB, TRUE);
WRITEBSTR(m_pSuffixStream, L"</IRETURNVALUE>");
// Create VALUE.OBJECTs
MapEnum (pEnum, 0, 0, NULL, NULL, pECB, pFlagsContext, TRUE);
}
break;
}
pEnum->Release ();
}
if (bMustFreeQueryString)
SysFreeString (pszQueryString);
}
// Release the IWbemContext object, if any
if(pContext)
pContext->Release();
pService->Release();
}
}
// In case of HTTP 1.1, We have to ensure that we write thr contents of m_pPrefixStream to the socket irrespective of whether the call failed or not
if(FAILED(hr) && m_iHttpVersion == WMI_XML_HTTP_VERSION_1_1)
SavePrefixAndBodyToIISSocket(m_pPrefixStream, NULL, pECB, TRUE);
return hr;
}
//***************************************************************************
//
// SCODE CXMLTranslator::EnumerateInstanceNames
//
// DESCRIPTION:
//
// Transforms the query result set into its equivalent XML representation
//
// PARAMETERS:
//
// pszNamespacePath The namespace path in which the object resides.
// pszClassName The class whose instance names are to be enumerated
// pXML On successful return addresses the XML document.
// The caller is responsible for freeing this BSTR
// using SysFreeString.
//
// RETURN VALUES:
//
// WBEM_S_NO_ERROR success, XML document is addressed by pXML
// WBEM_E_INVALID_PARAMETER bad input parameters
// WBEM_E_FAILED otherwise
//
// Other WBEM error codes may be returned by ConnectServer etc., in which
// case these are passed on to the caller.
//
//***************************************************************************
HRESULT CXMLTranslator::EnumerateInstanceNames (
BSTR pszNamespacePath,
BSTR pszClassName,
LPEXTENSION_CONTROL_BLOCK pECB,
IWbemContext *pFlagsContext
)
{
HRESULT hr = WBEM_E_FAILED;
if ((NULL == pszNamespacePath) || (NULL == pszClassName))
{
hr = WBEM_E_INVALID_PARAMETER;
}
else
{
// Connect to the requested namespace
IWbemServices *pService = NULL;
if (SUCCEEDED (hr = m_connectionCache.GetConnectionByPath (pszNamespacePath, &pService)))
{
// Create an IWbemContext Object if the client is WMI
IWbemContext *pContext = NULL;
if(m_pContext)
hr = CXmlToWmi::MapContextObject(m_pContext, &pContext);
if(SUCCEEDED(hr))
{
// Perform the query
IEnumWbemClassObject *pEnum = NULL;
BSTR bsQueryLang = NULL;
if(bsQueryLang = SysAllocString(L"WQL"))
{
LPWSTR pszQuery = NULL;
if(pszQuery = new WCHAR [ wcslen(L"select __RELPATH from ") + wcslen(pszClassName) + 1])
{
pszQuery[0] = NULL;
wcscat(pszQuery, L"select __RELPATH from ");
wcscat(pszQuery, pszClassName);
BSTR bsQuery = NULL;
if(bsQuery = SysAllocString(pszQuery))
{
// RAJESHR - Use semi sync and Forward only enumerator?
long lFlags = WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY;
if (SUCCEEDED (hr = pService->ExecQuery
(bsQueryLang, bsQuery, 0, pContext, &pEnum)))
{
// Ensure we have impersonation enabled
DWORD dwAuthnLevel, dwImpLevel;
GetAuthImp (pEnum, &dwAuthnLevel, &dwImpLevel);
if (RPC_C_IMP_LEVEL_IMPERSONATE != dwImpLevel)
SetInterfaceSecurity (pEnum, NULL, NULL, NULL, dwAuthnLevel, RPC_C_IMP_LEVEL_IMPERSONATE, EOAC_STATIC_CLOAKING);
switch(m_iHttpVersion)
{
// We write everything on to the prefix stream since there is no
// chunked encoding in HTTP 1.0
case WMI_XML_HTTP_VERSION_1_0:
{
// First Write an IRETURNVALUE to the Prefix Stream
WRITEBSTR(m_pPrefixStream, L"<IRETURNVALUE>");
// Now do the translation
MapEnumNames (m_pPrefixStream, pEnum, 2, pFlagsContext);
WRITEBSTR(m_pPrefixStream, L"</IRETURNVALUE>");
}
break;
case WMI_XML_HTTP_VERSION_1_1:
{
// Create a stream
IStream *pStream = NULL;
if (SUCCEEDED(hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream)))
{
// Now do the translation
if (SUCCEEDED(MapEnumNames (pStream, pEnum, 2, pFlagsContext)))
{
// First Write an IRETURNVALUE to the Prefix Stream
WRITEBSTR(m_pPrefixStream, L"<IRETURNVALUE>");
WRITEBSTR(pStream, L"</IRETURNVALUE>");
// Write the translation to the IIS Socket
SavePrefixAndBodyToIISSocket(m_pPrefixStream, pStream, pECB, TRUE);
}
pStream->Release ();
}
}
break;
}
pEnum->Release ();
}
SysFreeString (bsQuery);
}
else
hr = E_OUTOFMEMORY;
delete [] pszQuery;
}
else
hr = E_OUTOFMEMORY;
SysFreeString (bsQueryLang);
}
else
hr = E_OUTOFMEMORY;
}
// Release the IWbemContext object, if any
if(pContext)
pContext->Release();
pService->Release();
}
}
// In case of HTTP 1.1, We have to ensure that we write thr contents of m_pPrefixStream to the socket irrespective of whether the call failed or not
if(FAILED(hr) && m_iHttpVersion == WMI_XML_HTTP_VERSION_1_1)
SavePrefixAndBodyToIISSocket(m_pPrefixStream, NULL, pECB, TRUE);
return hr;
}
//***************************************************************************
//
// SCODE CXMLTranslator::EnumerateClassNames
//
// DESCRIPTION:
//
// Transforms the query result set into its equivalent XML representation
//
// PARAMETERS:
//
// pszNamespacePath The namespace path in which the object resides.
// pszClassName The class whose subclass names are to be enumerated
// bDeepInheritance Whether to do a deep inheritance
// pXML On successful return addresses the XML document.
// The caller is responsible for freeing this BSTR
// using SysFreeString.
//
// RETURN VALUES:
//
// WBEM_S_NO_ERROR success, XML document is addressed by pXML
// WBEM_E_INVALID_PARAMETER bad input parameters
// WBEM_E_FAILED otherwise
//
// Other WBEM error codes may be returned by ConnectServer etc., in which
// case these are passed on to the caller.
//
//***************************************************************************
HRESULT CXMLTranslator::EnumerateClassNames (
BSTR pszNamespacePath,
BSTR pszClassName,
BOOL bDeepInheritance,
LPEXTENSION_CONTROL_BLOCK pECB,
IWbemContext *pFlagsContext
)
{
HRESULT hr = WBEM_E_FAILED;
if ((NULL == pszNamespacePath) || (NULL == pszClassName))
{
hr = WBEM_E_INVALID_PARAMETER;
}
else
{
// Connect to the requested namespace
IWbemServices *pService = NULL;
if (SUCCEEDED (hr = m_connectionCache.GetConnectionByPath (pszNamespacePath, &pService)))
{
// Create an IWbemContext Object if the client is WMI
IWbemContext *pContext = NULL;
if(m_pContext)
hr = CXmlToWmi::MapContextObject(m_pContext, &pContext);
if(SUCCEEDED(hr))
{
// Perform the query
IEnumWbemClassObject *pEnum = NULL;
LONG lFlags = (bDeepInheritance) ? WBEM_FLAG_DEEP : WBEM_FLAG_SHALLOW;
// RAJESHR - Can this be done more efficiently via a schema query ?
lFlags |= (WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY);
if (SUCCEEDED (hr = pService->CreateClassEnum
(pszClassName, lFlags, pContext, &pEnum)))
{
// Ensure we have impersonation enabled
DWORD dwAuthnLevel, dwImpLevel;
GetAuthImp (pEnum, &dwAuthnLevel, &dwImpLevel);
if (RPC_C_IMP_LEVEL_IMPERSONATE != dwImpLevel)
SetInterfaceSecurity (pEnum, NULL, NULL, NULL, dwAuthnLevel, RPC_C_IMP_LEVEL_IMPERSONATE, EOAC_STATIC_CLOAKING);
switch(m_iHttpVersion)
{
// We write everything on to the prefix stream since there is no
// chunked encoding in HTTP 1.0
case WMI_XML_HTTP_VERSION_1_0:
{
// First Write an IRETURNVALUE to the Prefix Stream
WRITEBSTR(m_pPrefixStream, L"<IRETURNVALUE>");
// Now do the translation
MapClassNames (m_pPrefixStream, pEnum, pFlagsContext);
WRITEBSTR(m_pPrefixStream, L"</IRETURNVALUE>");
}
break;
case WMI_XML_HTTP_VERSION_1_1:
{
// Create a stream
IStream *pStream = NULL;
if (SUCCEEDED(hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream)))
{
// Now do the translation
if (SUCCEEDED(hr = MapClassNames (pStream, pEnum, pFlagsContext)))
{
// First Write an IRETURNVALUE to the Prefix Stream
WRITEBSTR(m_pPrefixStream, L"<IRETURNVALUE>");
WRITEBSTR(pStream, L"</IRETURNVALUE>");
// Write the translation to the IIS Socket
SavePrefixAndBodyToIISSocket(m_pPrefixStream, pStream, pECB, TRUE);
}
pStream->Release ();
}
}
break;
}
pEnum->Release ();
}
}
// Release the IWbemContext object, if any
if(pContext)
pContext->Release();
pService->Release();
}
}
// In case of HTTP 1.1, We have to ensure that we write thr contents of m_pPrefixStream to the socket irrespective of whether the call failed or not
if(FAILED(hr) && m_iHttpVersion == WMI_XML_HTTP_VERSION_1_1)
SavePrefixAndBodyToIISSocket(m_pPrefixStream, NULL, pECB, TRUE);
return hr;
}
//***************************************************************************
//
// SCODE CXMLTranslator::EnumerateInstances
//
// DESCRIPTION:
//
// Transforms the query result set nto its equivalent XML representation
//
// PARAMETERS:
//
// pszNamespacePath The namespace path in which the object resides.
// pszClassName The class to be enumerated
// bDeep Whether this enumeration is deep
// pXML On successful return addresses the XML document.
// The caller is responsible for freeing this BSTR
// using SysFreeString.
//
// RETURN VALUES:
//
// WBEM_S_NO_ERROR success, XML document is addressed by pXML
// WBEM_E_INVALID_PARAMETER bad input parameters
// WBEM_E_FAILED otherwise
//
// Other WBEM error codes may be returned by ConnectServer etc., in which
// case these are passed on to the caller.
//
//***************************************************************************
HRESULT CXMLTranslator::EnumerateInstances (
BSTR pszNamespacePath,
BSTR pszClassName,
VARIANT_BOOL bDeep,
BOOL bIsMicrosoftWMIClient,
DWORD dwNumProperties,
BSTR *pPropertyArray,
LPEXTENSION_CONTROL_BLOCK pECB,
IWbemContext *pFlagsContext
)
{
HRESULT hr = WBEM_E_FAILED;
if ((NULL == pszNamespacePath) || (NULL == pszClassName))
{
hr = WBEM_E_INVALID_PARAMETER;
}
else
{
// Connect to the requested namespace
IWbemServices *pService = NULL;
if (SUCCEEDED (hr = m_connectionCache.GetConnectionByPath (pszNamespacePath, &pService)))
{
// Create an IWbemContext Object if the client is WMI
IWbemContext *pContext = NULL;
if(m_pContext)
hr = CXmlToWmi::MapContextObject(m_pContext, &pContext);
if(SUCCEEDED(hr))
{
// Perform the Enumeration - RAJESHR if a property list is specified, can we make it more efficient using a Query?
IEnumWbemClassObject *pEnum = NULL;
long lFlags = WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY;
// DMTF and Microsoft have different interpretations of the Deep enumeration
// For DMTF, we always have to ask our CIMOM to do a Deep enumeration and post-process
// later. Whereas, for Microsoft we directly pass the flag as it is
if(bIsMicrosoftWMIClient)
{
if(VARIANT_TRUE == bDeep) lFlags |= WBEM_FLAG_DEEP;
}
else // For DMTF
lFlags |= WBEM_FLAG_DEEP;
// Check to see if this version of WMI supports the WBEM_FLAG_USE_AMENDED_QUALIFIERS flag
// Otherwise, make a best effort call with no flags.
// We need this to get the properties that have the "amended" qualifier on them
if(WBEM_E_INVALID_PARAMETER == (hr = pService->CreateInstanceEnum (pszClassName, lFlags | WBEM_FLAG_USE_AMENDED_QUALIFIERS, pContext, &pEnum)))
hr = pService->CreateInstanceEnum (pszClassName, lFlags, pContext, &pEnum);
if (WBEM_S_NO_ERROR == hr)
{
// Ensure we have impersonation enabled
DWORD dwAuthnLevel, dwImpLevel;
GetAuthImp (pEnum, &dwAuthnLevel, &dwImpLevel);
if (RPC_C_IMP_LEVEL_IMPERSONATE != dwImpLevel)
SetInterfaceSecurity (pEnum, NULL, NULL, NULL, dwAuthnLevel, RPC_C_IMP_LEVEL_IMPERSONATE, EOAC_STATIC_CLOAKING);
switch(m_iHttpVersion)
{
// We write everything on to the prefix stream since there is no
// chunked encoding in HTTP 1.0
case WMI_XML_HTTP_VERSION_1_0:
{
// First Write an IRETURNVALUE to the Prefix Stream
WRITEBSTR(m_pPrefixStream, L"<IRETURNVALUE>");
// Now do the translation
// For Deep Enumerations and WMI Enumerations, we dont do anything special
// For shallow instance enumerations we have to give the class basis
// the CWmiToXml object so it can emulate DMTF-style shallow enumeration
if (VARIANT_TRUE == bDeep || bIsMicrosoftWMIClient)
MapEnum (pEnum, 1, dwNumProperties, pPropertyArray, NULL, pECB, pFlagsContext, FALSE, m_pPrefixStream);
else
MapEnum (pEnum, 1, dwNumProperties, pPropertyArray, pszClassName, pECB, pFlagsContext, FALSE, m_pPrefixStream);
WRITEBSTR(m_pPrefixStream, L"</IRETURNVALUE>");
}
break;
case WMI_XML_HTTP_VERSION_1_1:
{
// First Write an IRETURNVALUE to the Prefix Stream
WRITEBSTR(m_pPrefixStream, L"<IRETURNVALUE>");
SaveStreamToIISSocket(m_pPrefixStream, pECB, TRUE);
WRITEBSTR(m_pSuffixStream, L"</IRETURNVALUE>");
// Now do the translation
// For shallow instance enumerations we have to give the class basis
// the CWmiToXml object so it can emulate DMTF-style shallow enumeration
if (VARIANT_TRUE == bDeep || bIsMicrosoftWMIClient)
MapEnum (pEnum, 1, dwNumProperties, pPropertyArray, NULL, pECB, pFlagsContext, TRUE);
else
MapEnum (pEnum, 1, dwNumProperties, pPropertyArray, pszClassName, pECB, pFlagsContext, TRUE);
}
break;
}
pEnum->Release ();
}
}
// Release the IWbemContext object, if any
if(pContext)
pContext->Release();
pService->Release();
}
}
// In case of HTTP 1.1, We have to ensure that we write thr contents of m_pPrefixStream to the socket irrespective of whether the call failed or not
if(FAILED(hr) && m_iHttpVersion == WMI_XML_HTTP_VERSION_1_1)
SavePrefixAndBodyToIISSocket(m_pPrefixStream, NULL, pECB, TRUE);
return hr;
}
//***************************************************************************
//
// SCODE CXMLTranslator::EnumerateClasses
//
// DESCRIPTION:
//
// Transforms the query result set nto its equivalent XML representation
//
// PARAMETERS:
//
// pszNamespacePath The namespace path in which the object resides.
// pszClassName The class to be enumerated
// bDeep Whether this enumeration is deep
// pXML On successful return addresses the XML document.
// The caller is responsible for freeing this BSTR
// using SysFreeString.
//
// RETURN VALUES:
//
// WBEM_S_NO_ERROR success, XML document is addressed by pXML
// WBEM_E_INVALID_PARAMETER bad input parameters
// WBEM_E_FAILED otherwise
//
// Other WBEM error codes may be returned by ConnectServer etc., in which
// case these are passed on to the caller.
//
//***************************************************************************
HRESULT CXMLTranslator::EnumerateClasses (
BSTR pszNamespacePath,
BSTR pszClassName,
VARIANT_BOOL bDeep,
DWORD dwNumProperties,
BSTR *pPropertyArray,
LPEXTENSION_CONTROL_BLOCK pECB,
IWbemContext *pFlagsContext
)
{
HRESULT hr = WBEM_E_FAILED;
if ((NULL == pszNamespacePath) || (NULL == pszClassName))
{
hr = WBEM_E_INVALID_PARAMETER;
}
else
{
// Connect to the requested namespace
IWbemServices *pService = NULL;
if (SUCCEEDED (hr = m_connectionCache.GetConnectionByPath (pszNamespacePath, &pService)))
{
// Create an IWbemContext Object if the client is WMI
IWbemContext *pContext = NULL;
if(m_pContext)
hr = CXmlToWmi::MapContextObject(m_pContext, &pContext);
if(SUCCEEDED(hr))
{
// Perform the query
IEnumWbemClassObject *pEnum = NULL;
long lDeepFlag = WBEM_FLAG_DEEP;
if(bDeep == VARIANT_FALSE)
lDeepFlag = WBEM_FLAG_SHALLOW;
// Check to see if this version of WMI supports the WBEM_FLAG_USE_AMENDED_QUALIFIERS flag
// Otherwise, make a best effort call with no flags.
// We need this to get the properties that have the "amended" qualifier on them
lDeepFlag |= WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY;
if(WBEM_E_INVALID_PARAMETER == (hr = pService->CreateClassEnum (pszClassName, lDeepFlag | WBEM_FLAG_USE_AMENDED_QUALIFIERS, pContext, &pEnum)))
hr = pService->CreateClassEnum (pszClassName, lDeepFlag, pContext, &pEnum);
if (WBEM_S_NO_ERROR == hr)
{
// Ensure we have impersonation enabled
DWORD dwAuthnLevel, dwImpLevel;
GetAuthImp (pEnum, &dwAuthnLevel, &dwImpLevel);
if (RPC_C_IMP_LEVEL_IMPERSONATE != dwImpLevel)
SetInterfaceSecurity (pEnum, NULL, NULL, NULL, dwAuthnLevel, RPC_C_IMP_LEVEL_IMPERSONATE, EOAC_STATIC_CLOAKING);
switch(m_iHttpVersion)
{
// We write everything on to the prefix stream since there is no
// chunked encoding in HTTP 1.0
case WMI_XML_HTTP_VERSION_1_0:
{
// First Write an IRETURNVALUE to the Prefix Stream
WRITEBSTR(m_pPrefixStream, L"<IRETURNVALUE>");
// Now do the translation
MapEnum (pEnum, 0, dwNumProperties, pPropertyArray, NULL, pECB, pFlagsContext, FALSE, m_pPrefixStream);
WRITEBSTR(m_pPrefixStream, L"</IRETURNVALUE>");
}
break;
case WMI_XML_HTTP_VERSION_1_1:
{
// First Write an IRETURNVALUE to the Prefix Stream
WRITEBSTR(m_pPrefixStream, L"<IRETURNVALUE>");
SaveStreamToIISSocket(m_pPrefixStream, pECB, (m_iHttpVersion == WMI_XML_HTTP_VERSION_1_1));
WRITEBSTR(m_pSuffixStream, L"</IRETURNVALUE>");
// Now do the translation
MapEnum (pEnum, 0, dwNumProperties, pPropertyArray, NULL, pECB, pFlagsContext, (m_iHttpVersion == WMI_XML_HTTP_VERSION_1_1));
}
break;
}
pEnum->Release ();
}
}
// Release the IWbemContext object, if any
if(pContext)
pContext->Release();
pService->Release();
}
}
// In case of HTTP 1.1, We have to ensure that we write thr contents of m_pPrefixStream to the socket irrespective of whether the call failed or not
if(FAILED(hr) && m_iHttpVersion == WMI_XML_HTTP_VERSION_1_1)
SavePrefixAndBodyToIISSocket(m_pPrefixStream, NULL, pECB, TRUE);
return hr;
}
//***************************************************************************
//
// SCODE CXMLTranslator::Associators
//
// DESCRIPTION:
//
// Performs an "ASSOCIATORS OF" query and transforms the result into XML
//
// PARAMETERS:
//
// pszNamespacePath The namespace path in which the object resides.
// pszClassName The class to be enumerated
// pXML On successful return addresses the XML document.
// The caller is responsible for freeing this BSTR
// using SysFreeString.
//
// RETURN VALUES:
//
// WBEM_S_NO_ERROR success, XML document is addressed by pXML
// WBEM_E_INVALID_PARAMETER bad input parameters
// WBEM_E_FAILED otherwise
//
// Other WBEM error codes may be returned by ConnectServer etc., in which
// case these are passed on to the caller.
//
//***************************************************************************
HRESULT CXMLTranslator::Associators (
BSTR pszNamespacePath,
BSTR pszObjectName,
BSTR pszAssocClass,
BSTR pszResultClass,
BSTR pszRole,
BSTR pszResultRole,
DWORD dwNumProperties,
BSTR *pPropertyArray,
LPEXTENSION_CONTROL_BLOCK pECB,
IWbemContext *pFlagsContext
)
{
HRESULT hr = WBEM_E_FAILED;
if ((NULL == pszNamespacePath) || (NULL == pszObjectName))
{
hr = WBEM_E_INVALID_PARAMETER;
}
else
{
// Connect to the requested namespace
IWbemServices *pService = NULL;
if (SUCCEEDED (hr = m_connectionCache.GetConnectionByPath (pszNamespacePath, &pService)))
{
// Create an IWbemContext Object if the client is WMI
IWbemContext *pContext = NULL;
if(m_pContext)
hr = CXmlToWmi::MapContextObject(m_pContext, &pContext);
if(SUCCEEDED(hr))
{
// Perform the query
IEnumWbemClassObject *pEnum = NULL;
WCHAR *strPropertyList = BuildPropertyList (dwNumProperties, pPropertyArray);
BSTR bsQueryLang = NULL;
bsQueryLang = SysAllocString(L"WQL");
// Build the ASSOCIATORS OF query
BSTR bsQuery = FormatAssociatorsQuery (pszObjectName, pszAssocClass, pszResultClass,
pszResultRole, pszRole, FALSE, FALSE, NULL, NULL);
// Check to see if this version of WMI supports the WBEM_FLAG_USE_AMENDED_QUALIFIERS flag
// Otherwise, make a best effort call with no flags.
// We need this to get the properties that have the "amended" qualifier on them
long lFlags = WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY;
if(WBEM_E_INVALID_PARAMETER == (hr = pService->ExecQuery (bsQueryLang, bsQuery, lFlags | WBEM_FLAG_USE_AMENDED_QUALIFIERS, pContext, &pEnum)))
hr = pService->ExecQuery (bsQueryLang, bsQuery, lFlags, pContext, &pEnum);
SysFreeString (bsQueryLang);
SysFreeString (bsQuery);
if (WBEM_S_NO_ERROR == hr)
{
// Ensure we have impersonation enabled
DWORD dwAuthnLevel, dwImpLevel;
GetAuthImp (pEnum, &dwAuthnLevel, &dwImpLevel);
if (RPC_C_IMP_LEVEL_IMPERSONATE != dwImpLevel)
SetInterfaceSecurity (pEnum, NULL, NULL, NULL, dwAuthnLevel, RPC_C_IMP_LEVEL_IMPERSONATE, EOAC_STATIC_CLOAKING);
switch(m_iHttpVersion)
{
// We write everything on to the prefix stream since there is no
// chunked encoding in HTTP 1.0
case WMI_XML_HTTP_VERSION_1_0:
{
// First Write an IRETURNVALUE to the Prefix Stream
WRITEBSTR(m_pPrefixStream, L"<IRETURNVALUE>");
MapEnum (pEnum, 3, 0, NULL, NULL, pECB, pFlagsContext, FALSE, m_pPrefixStream);
WRITEBSTR(m_pPrefixStream, L"</IRETURNVALUE>");
}
break;
case WMI_XML_HTTP_VERSION_1_1:
{
// First Write an IRETURNVALUE to the Prefix Stream
WRITEBSTR(m_pPrefixStream, L"<IRETURNVALUE>");
SaveStreamToIISSocket(m_pPrefixStream, pECB, TRUE);
WRITEBSTR(m_pSuffixStream, L"</IRETURNVALUE>");
MapEnum (pEnum, 3, 0, NULL, NULL, pECB, pFlagsContext, TRUE);
}
break;
}
pEnum->Release ();
}
}
// Release the IWbemContext object, if any
if(pContext)
pContext->Release();
pService->Release();
}
}
// In case of HTTP 1.1, We have to ensure that we write thr contents of m_pPrefixStream to the socket irrespective of whether the call failed or not
if(FAILED(hr) && m_iHttpVersion == WMI_XML_HTTP_VERSION_1_1)
SavePrefixAndBodyToIISSocket(m_pPrefixStream, NULL, pECB, TRUE);
return hr;
}
//***************************************************************************
//
// SCODE CXMLTranslator::AssociatorNames
//
// DESCRIPTION:
//
// Performs an "ASSOCIATORS OF" query, gets the names and transforms the
/// result into XML
//
// PARAMETERS:
//
// pszNamespacePath The namespace path in which the object resides.
// pszObjectName The object whose assocaitors are required
// pXML On successful return addresses the XML document.
// The caller is responsible for freeing this BSTR
// using SysFreeString.
//
// RETURN VALUES:
//
// WBEM_S_NO_ERROR success, XML document is addressed by pXML
// WBEM_E_INVALID_PARAMETER bad input parameters
// WBEM_E_FAILED otherwise
//
// Other WBEM error codes may be returned by ConnectServer etc., in which
// case these are passed on to the caller.
//
//***************************************************************************
HRESULT CXMLTranslator::AssociatorNames (
BSTR pszNamespacePath,
BSTR pszObjectName,
BSTR pszAssocClass,
BSTR pszResultClass,
BSTR pszRole,
BSTR pszResultRole,
LPEXTENSION_CONTROL_BLOCK pECB,
IWbemContext *pFlagsContext
)
{
HRESULT hr = WBEM_E_FAILED;
if ((NULL == pszNamespacePath) || (NULL == pszObjectName))
{
hr = WBEM_E_INVALID_PARAMETER;
}
else
{
// Connect to the requested namespace
IWbemServices *pService = NULL;
if (SUCCEEDED (hr = m_connectionCache.GetConnectionByPath (pszNamespacePath, &pService)))
{
// Create an IWbemContext Object if the client is WMI
IWbemContext *pContext = NULL;
if(m_pContext)
hr = CXmlToWmi::MapContextObject(m_pContext, &pContext);
if(SUCCEEDED(hr))
{
// Perform the query
IEnumWbemClassObject *pEnum = NULL;
BSTR bsQueryLang = NULL;
bsQueryLang = SysAllocString(L"WQL");
// Build the ASSOCIATORS OF query
BSTR bsQuery = FormatAssociatorsQuery (pszObjectName, pszAssocClass, pszResultClass,
pszResultRole, pszRole, FALSE, FALSE, NULL, NULL);
// RAJESHR - Use semi sync and Forward only enumerator?
long lFlags = WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY;
if(SUCCEEDED(hr = pService->ExecQuery (bsQueryLang, bsQuery, lFlags, pContext, &pEnum)))
{
// Ensure we have impersonation enabled
DWORD dwAuthnLevel, dwImpLevel;
GetAuthImp (pEnum, &dwAuthnLevel, &dwImpLevel);
if (RPC_C_IMP_LEVEL_IMPERSONATE != dwImpLevel)
SetInterfaceSecurity (pEnum, NULL, NULL, NULL, dwAuthnLevel, RPC_C_IMP_LEVEL_IMPERSONATE, EOAC_STATIC_CLOAKING);
switch(m_iHttpVersion)
{
// We write everything on to the prefix stream since there is no
// chunked encoding in HTTP 1.0
case WMI_XML_HTTP_VERSION_1_0:
{
// First Write an IRETURNVALUE to the Prefix Stream
WRITEBSTR(m_pPrefixStream, L"<IRETURNVALUE>");
// Now do the translation
MapEnumNames (m_pPrefixStream, pEnum, 3, pFlagsContext);
WRITEBSTR(m_pPrefixStream, L"</IRETURNVALUE>");
}
break;
case WMI_XML_HTTP_VERSION_1_1:
{
// Create a stream
IStream *pStream = NULL;
if (SUCCEEDED(hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream)))
{
// Now do the translation
if (SUCCEEDED(MapEnumNames (pStream, pEnum, 3, pFlagsContext)))
{
// First Write an IRETURNVALUE to the Prefix Stream
WRITEBSTR(m_pPrefixStream, L"<IRETURNVALUE>");
WRITEBSTR(pStream, L"</IRETURNVALUE>");
// Write the translation to the IIS Socket
SavePrefixAndBodyToIISSocket(m_pPrefixStream, pStream, pECB, m_iHttpVersion == WMI_XML_HTTP_VERSION_1_1);
}
pStream->Release ();
}
}
break;
}
pEnum->Release ();
}
SysFreeString (bsQueryLang);
SysFreeString (bsQuery);
}
// Release the IWbemContext object, if any
if(pContext)
pContext->Release();
pService->Release();
}
}
// In case of HTTP 1.1, We have to ensure that we write thr contents of m_pPrefixStream to the socket irrespective of whether the call failed or not
if(FAILED(hr) && m_iHttpVersion == WMI_XML_HTTP_VERSION_1_1)
SavePrefixAndBodyToIISSocket(m_pPrefixStream, NULL, pECB, TRUE);
return hr;
}
//***************************************************************************
//
// SCODE CXMLTranslator::References
//
// DESCRIPTION:
//
// Performs an "REFERENCES OF" query and transforms the result into XML
//
// PARAMETERS:
//
// pszNamespacePath The namespace path in which the object resides.
// pszClassName The class to be enumerated
// pXML On successful return addresses the XML document.
// The caller is responsible for freeing this BSTR
// using SysFreeString.
//
// RETURN VALUES:
//
// WBEM_S_NO_ERROR success, XML document is addressed by pXML
// WBEM_E_INVALID_PARAMETER bad input parameters
// WBEM_E_FAILED otherwise
//
// Other WBEM error codes may be returned by ConnectServer etc., in which
// case these are passed on to the caller.
//
//***************************************************************************
HRESULT CXMLTranslator::References (
BSTR pszNamespacePath,
BSTR pszObjectName,
BSTR pszResultClass,
BSTR pszRole,
DWORD dwNumProperties,
BSTR *pPropertyArray,
LPEXTENSION_CONTROL_BLOCK pECB,
IWbemContext *pFlagsContext
)
{
HRESULT hr = WBEM_E_FAILED;
if ((NULL == pszNamespacePath) || (NULL == pszObjectName))
{
hr = WBEM_E_INVALID_PARAMETER;
}
else
{
// Connect to the requested namespace
IWbemServices *pService = NULL;
if (SUCCEEDED (hr = m_connectionCache.GetConnectionByPath (pszNamespacePath, &pService)))
{
// Create an IWbemContext Object if the client is WMI
IWbemContext *pContext = NULL;
if(m_pContext)
hr = CXmlToWmi::MapContextObject(m_pContext, &pContext);
if(SUCCEEDED(hr))
{
// Perform the query
IEnumWbemClassObject *pEnum = NULL;
WCHAR *strPropertyList = BuildPropertyList (dwNumProperties, pPropertyArray);
BSTR bsQueryLang = SysAllocString(L"WQL");
// Build the ASSOCIATORS OF query
BSTR bsQuery = FormatReferencesQuery (pszObjectName, pszResultClass,
pszRole, FALSE, FALSE, NULL);
// Check to see if this version of WMI supports the WBEM_FLAG_USE_AMENDED_QUALIFIERS flag
// Otherwise, make a best effort call with no flags.
// We need this to get the properties that have the "amended" qualifier on them
long lFlags = WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY;
if(WBEM_E_INVALID_PARAMETER == (hr = pService->ExecQuery (bsQueryLang, bsQuery, lFlags | WBEM_FLAG_USE_AMENDED_QUALIFIERS, pContext, &pEnum)))
hr = pService->ExecQuery (bsQueryLang, bsQuery, lFlags, pContext, &pEnum);
SysFreeString (bsQueryLang);
SysFreeString (bsQuery);
if (WBEM_S_NO_ERROR == hr)
{
// Ensure we have impersonation enabled
DWORD dwAuthnLevel, dwImpLevel;
GetAuthImp (pEnum, &dwAuthnLevel, &dwImpLevel);
if (RPC_C_IMP_LEVEL_IMPERSONATE != dwImpLevel)
SetInterfaceSecurity (pEnum, NULL, NULL, NULL, dwAuthnLevel, RPC_C_IMP_LEVEL_IMPERSONATE, EOAC_STATIC_CLOAKING);
switch(m_iHttpVersion)
{
// We write everything on to the prefix stream since there is no
// chunked encoding in HTTP 1.0
case WMI_XML_HTTP_VERSION_1_0:
{
// First Write an IRETURNVALUE to the Prefix Stream
WRITEBSTR(m_pPrefixStream, L"<IRETURNVALUE>");
MapEnum (pEnum, 3, 0, NULL, NULL, pECB, pFlagsContext, FALSE, m_pPrefixStream);
WRITEBSTR(m_pPrefixStream, L"</IRETURNVALUE>");
}
break;
case WMI_XML_HTTP_VERSION_1_1:
{
// First Write an IRETURNVALUE to the Prefix Stream
WRITEBSTR(m_pPrefixStream, L"<IRETURNVALUE>");
SaveStreamToIISSocket(m_pPrefixStream, pECB, TRUE);
WRITEBSTR(m_pSuffixStream, L"</IRETURNVALUE>");
MapEnum (pEnum, 3, 0, NULL, NULL, pECB, pFlagsContext, TRUE);
}
break;
}
pEnum->Release ();
}
}
// Release the IWbemContext object, if any
if(pContext)
pContext->Release();
pService->Release();
}
}
// In case of HTTP 1.1, We have to ensure that we write thr contents of m_pPrefixStream to the socket irrespective of whether the call failed or not
if(FAILED(hr) && m_iHttpVersion == WMI_XML_HTTP_VERSION_1_1)
SavePrefixAndBodyToIISSocket(m_pPrefixStream, NULL, pECB, TRUE);
return hr;
}
//***************************************************************************
//
// SCODE CXMLTranslator::ReferenceNames
//
// DESCRIPTION:
//
// Performs an "REFERENCES OF" query, gets the names and transforms the
/// result into XML
//
// PARAMETERS:
//
// pszNamespacePath The namespace path in which the object resides.
// pszObjectName The object whose assocaitors are required
// pXML On successful return addresses the XML document.
// The caller is responsible for freeing this BSTR
// using SysFreeString.
//
// RETURN VALUES:
//
// WBEM_S_NO_ERROR success, XML document is addressed by pXML
// WBEM_E_INVALID_PARAMETER bad input parameters
// WBEM_E_FAILED otherwise
//
// Other WBEM error codes may be returned by ConnectServer etc., in which
// case these are passed on to the caller.
//
//***************************************************************************
HRESULT CXMLTranslator::ReferenceNames (
BSTR pszNamespacePath,
BSTR pszObjectName,
BSTR pszResultClass,
BSTR pszRole,
LPEXTENSION_CONTROL_BLOCK pECB,
IWbemContext *pFlagsContext
)
{
HRESULT hr = WBEM_E_FAILED;
if ((NULL == pszNamespacePath) || (NULL == pszObjectName))
{
hr = WBEM_E_INVALID_PARAMETER;
}
else
{
// Connect to the requested namespace
IWbemServices *pService = NULL;
if (SUCCEEDED (hr = m_connectionCache.GetConnectionByPath (pszNamespacePath, &pService)))
{
// Create an IWbemContext Object if the client is WMI
IWbemContext *pContext = NULL;
if(m_pContext)
hr = CXmlToWmi::MapContextObject(m_pContext, &pContext);
if(SUCCEEDED(hr))
{
// Perform the query
IEnumWbemClassObject *pEnum = NULL;
BSTR bsQueryLang = SysAllocString(L"WQL");
// Build the ASSOCIATORS OF query
BSTR bsQuery = FormatReferencesQuery (pszObjectName, pszResultClass,
pszRole, FALSE, FALSE, NULL);
// RAJESHR - Use semi sync and Forward only enumerator?
if(SUCCEEDED(hr = pService->ExecQuery (bsQueryLang, bsQuery, 0, pContext, &pEnum)))
{
// Ensure we have impersonation enabled
DWORD dwAuthnLevel, dwImpLevel;
GetAuthImp (pEnum, &dwAuthnLevel, &dwImpLevel);
if (RPC_C_IMP_LEVEL_IMPERSONATE != dwImpLevel)
SetInterfaceSecurity (pEnum, NULL, NULL, NULL, dwAuthnLevel, RPC_C_IMP_LEVEL_IMPERSONATE, EOAC_STATIC_CLOAKING);
switch(m_iHttpVersion)
{
// We write everything on to the prefix stream since there is no
// chunked encoding in HTTP 1.0
case WMI_XML_HTTP_VERSION_1_0:
{
// First Write an IRETURNVALUE to the Prefix Stream
WRITEBSTR(m_pPrefixStream, L"<IRETURNVALUE>");
// Now do the translation
MapEnumNames (m_pPrefixStream, pEnum, 3, pFlagsContext);
WRITEBSTR(m_pPrefixStream, L"</IRETURNVALUE>");
}
break;
case WMI_XML_HTTP_VERSION_1_1:
{
// Create a stream
IStream *pStream = NULL;
if (SUCCEEDED(hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream)))
{
// Now do the translation
if (SUCCEEDED(MapEnumNames (pStream, pEnum, 3, pFlagsContext)))
{
// First Write an IRETURNVALUE to the Prefix Stream
WRITEBSTR(m_pPrefixStream, L"<IRETURNVALUE>");
WRITEBSTR(pStream, L"</IRETURNVALUE>");
// Write the translation to the IIS Socket
SavePrefixAndBodyToIISSocket(m_pPrefixStream, pStream, pECB, m_iHttpVersion == WMI_XML_HTTP_VERSION_1_1);
}
pStream->Release ();
}
}
break;
}
pEnum->Release ();
}
SysFreeString (bsQueryLang);
SysFreeString (bsQuery);
}
// Release the IWbemContext object, if any
if(pContext)
pContext->Release();
pService->Release();
}
}
// In case of HTTP 1.1, We have to ensure that we write thr contents of m_pPrefixStream to the socket irrespective of whether the call failed or not
if(FAILED(hr) && m_iHttpVersion == WMI_XML_HTTP_VERSION_1_1)
SavePrefixAndBodyToIISSocket(m_pPrefixStream, NULL, pECB, TRUE);
return hr;
}
HRESULT CXMLTranslator::ExecuteMethod (
BSTR pszNamespacePath,
BSTR pszObjPath,
BSTR pszMethodName,
BOOLEAN isStaticMethod,
CParameterMap *pParameterMap,
LPEXTENSION_CONTROL_BLOCK pECB,
IWbemContext *pFlagsContext
)
{
// In case of HTTP 1.1, We have to ensure that we write thr contents of m_pPrefixStream to the socket irrespective of whether the call failed or not
if(m_iHttpVersion == WMI_XML_HTTP_VERSION_1_1)
SavePrefixAndBodyToIISSocket(m_pPrefixStream, NULL, pECB, TRUE);
HRESULT hr = WBEM_E_FAILED;
if ( (NULL == pszNamespacePath) || (NULL == pszObjPath) || (NULL == pszMethodName))
{
hr = WBEM_E_INVALID_PARAMETER;
}
else
{
// Connect to the requested namespace
IWbemServices *pService = NULL;
if (SUCCEEDED (hr = m_connectionCache.GetConnectionByPath (pszNamespacePath, &pService)))
{
// Create an IWbemContext Object if the client is WMI
IWbemContext *pContext = NULL;
if(m_pContext)
hr = CXmlToWmi::MapContextObject(m_pContext, &pContext);
if(SUCCEEDED(hr))
{
// Get the class to get at the method definition
IWbemClassObject *pClass = NULL;
IWbemClassObject *pInstance = NULL;
if(isStaticMethod)
{
hr = pService->GetObject(pszObjPath, 0, 0, &pClass, NULL);
}
else
{
if(SUCCEEDED(hr = pService->GetObject(pszObjPath, 0, 0, &pInstance, NULL)))
{
// Get the __CLASS property
BSTR strClassProp = NULL;
if(strClassProp = SysAllocString(L"__CLASS"))
{
VARIANT classNameVariant;
VariantInit(&classNameVariant);
if(SUCCEEDED(hr = pInstance->Get(strClassProp, 0, &classNameVariant, NULL, NULL)))
{
hr = pService->GetObject(classNameVariant.bstrVal, 0, 0, &pClass, NULL);
VariantClear(&classNameVariant);
}
SysFreeString(strClassProp);
}
else
hr = E_OUTOFMEMORY;
}
}
// Now we have the class definition. Get the Method definition
if(SUCCEEDED(hr))
{
IWbemClassObject *pInSignature = NULL;
if(SUCCEEDED(hr = pClass->GetMethod(pszMethodName, 0, &pInSignature, NULL)))
{
// Form an instance for the input parameters
IWbemClassObject *pMethodParameters = NULL;
if(SUCCEEDED(hr = FormMethodParameters(pszNamespacePath, pInSignature, pParameterMap, &pMethodParameters)))
{
IWbemClassObject *pOutputParameters= NULL;
if(SUCCEEDED(hr = pService->ExecMethod(pszObjPath, pszMethodName, 0, pContext, pMethodParameters, &pOutputParameters, NULL)))
{
// We dont use chunked encoding for ExecMethod responses
// Instead we write everything to the prefix stream for HTTP1.0 or the Suffix stream for HTTP 1.1
// Create the convertor
IWbemXMLConvertor *pConvertor = NULL;
if(SUCCEEDED(hr = CreateXMLTranslator(&pConvertor)))
{
// Now do the translation
if (SUCCEEDED(hr = pConvertor->MapMethodResultToXML(pOutputParameters, pFlagsContext,
(m_iHttpVersion == WMI_XML_HTTP_VERSION_1_1) ? m_pSuffixStream : m_pPrefixStream)))
{
}
pConvertor->Release();
}
pOutputParameters->Release();
}
pMethodParameters->Release();
}
pInSignature->Release();
}
}
// Release the instance and class associated with this method
if(pClass)
pClass->Release();
if(pInstance)
pInstance->Release();
}
// Release the IWbemContext object, if any
if(pContext)
pContext->Release();
pService->Release();
}
}
return hr;
}
// Take the paramters from the input map and fill them into the IWbemClassObject
HRESULT CXMLTranslator::FormMethodParameters(
BSTR pszNamespacePath,
IWbemClassObject *pInSignature,
CParameterMap *pParameterMap,
IWbemClassObject **ppMethodParameters)
{
HRESULT hr = WBEM_E_FAILED;
*ppMethodParameters = NULL;
if(SUCCEEDED(hr = pInSignature->SpawnInstance(0, ppMethodParameters)))
{
if(SUCCEEDED(hr = pInSignature->BeginEnumeration(WBEM_FLAG_NONSYSTEM_ONLY)))
{
BSTR strName = NULL;
VARIANT variant;
VariantInit(&variant);
CIMTYPE cimType;
while(SUCCEEDED(hr = pInSignature->Next(0, &strName, &variant, &cimType, NULL)) && hr != WBEM_S_NO_MORE_DATA)
{
// Get the property from the property map
// We get one of (VALUE|VALUE.REFERENCE|VALUE.ARRAY|VALUE.REFARRAY|VALUE.OBJECT|VALUE.OBJECTARRAY)
// in pPropertyValue
IXMLDOMNode *pPropertyValue = NULL;
if(pParameterMap->Lookup(strName, pPropertyValue))
{
// Map the parameter value to the property value
switch(cimType)
{
case CIM_SINT8:
case CIM_UINT8:
case CIM_SINT16:
case CIM_UINT16:
case CIM_UINT32:
case CIM_SINT32:
case CIM_REAL32:
case CIM_REAL64:
case CIM_BOOLEAN:
case CIM_STRING:
case CIM_DATETIME:
{
BSTR strPropertyValue = NULL;
if(SUCCEEDED(pPropertyValue->get_text(&strPropertyValue)))
{
hr = CXmlToWmi::MapStringValue(strPropertyValue, variant, cimType);
SysFreeString(strPropertyValue);
}
}
break;
case CIM_SINT8|CIM_FLAG_ARRAY:
case CIM_UINT8|CIM_FLAG_ARRAY:
case CIM_SINT16|CIM_FLAG_ARRAY:
case CIM_UINT16|CIM_FLAG_ARRAY:
case CIM_UINT32|CIM_FLAG_ARRAY:
case CIM_SINT32|CIM_FLAG_ARRAY:
case CIM_REAL32|CIM_FLAG_ARRAY:
case CIM_REAL64|CIM_FLAG_ARRAY:
case CIM_BOOLEAN|CIM_FLAG_ARRAY:
case CIM_STRING|CIM_FLAG_ARRAY:
case CIM_DATETIME|CIM_FLAG_ARRAY:
hr = CXmlToWmi::MapStringArrayValue(pPropertyValue, variant, cimType);
break;
case CIM_REFERENCE:
hr = CXmlToWmi::MapReferenceValue(pPropertyValue, variant);
break;
case CIM_REFERENCE|CIM_FLAG_ARRAY:
hr = CXmlToWmi::MapReferenceArrayValue(pPropertyValue, variant);
break;
case CIM_OBJECT:
case CIM_OBJECT|CIM_FLAG_ARRAY:
{
// Ugh - these types require us to connect to Cimom to fetch the class of the embedded object
// Connect to the requested namespace
IWbemServices *pService = NULL;
if (SUCCEEDED (hr = m_connectionCache.GetConnectionByPath (pszNamespacePath, &pService)))
{
CXmlToWmi xmlToWmi;
if(SUCCEEDED(hr = xmlToWmi.Initialize(NULL, pService, NULL)))
{
if(cimType == CIM_OBJECT)
hr = xmlToWmi.MapObjectValue(pPropertyValue, variant);
else
hr = xmlToWmi.MapObjectArrayValue(pPropertyValue, variant);
}
pService->Release();
}
}
break;
}
if(SUCCEEDED(hr))
hr = (*ppMethodParameters)->Put(strName, 0, &variant, NULL);
// No Need to delete/release the result of the call to LookUp()
// since we're only using pointers
}
VariantClear(&variant);
SysFreeString(strName);
}
pInSignature->EndEnumeration();
}
}
if(FAILED(hr))
{
if(*ppMethodParameters)
(*ppMethodParameters)->Release();
}
return hr;
}
WCHAR *BuildPropertyList (DWORD dwNumProperties, BSTR *pPropertyArray)
{
WCHAR *pstrPropertyList = NULL;
DWORD dwTotalMemory = 0;
// Go thru the list and collect the amount of memory required for converting
// this list of property names into a comma-separated list (one for the comma)
for (DWORD i = 0; i < dwNumProperties; i++)
dwTotalMemory += wcslen(pPropertyArray [i]);
if (dwTotalMemory)
{
if(pstrPropertyList = new WCHAR[dwTotalMemory + dwNumProperties])
{
pstrPropertyList [0] = NULL;
for(i=0; i<dwNumProperties; i++)
{
wcscat(pstrPropertyList, pPropertyArray[i]);
if(i != dwNumProperties-1)
wcscat(pstrPropertyList, L",");
}
}
}
return pstrPropertyList;
}
//***************************************************************************
//
// BSTR FormatAssociatorsQuery
//
// Description:
//
// Takes the parameters to an AssociatorsOf call and constructs a WQL
// query string from them.
//
// Returns: The constructed WQL query; this must be freed using
// SysFreeString by the caller.
//
// pdispparams the input dispatch parameters
//
//***************************************************************************
BSTR FormatAssociatorsQuery
(
BSTR strObjectPath,
BSTR strAssocClass,
BSTR strResultClass,
BSTR strResultRole,
BSTR strRole,
VARIANT_BOOL bClassesOnly,
VARIANT_BOOL bSchemaOnly,
BSTR strRequiredAssocQualifier,
BSTR strRequiredQualifier
)
{
BSTR bsQuery = NULL;
// Get the length of the string:
// associators of {SourceObject} where
// AssocClass = AssocClassName
// ClassDefsOnly
// SchemaOnly
// RequiredAssocQualifier = QualifierName
// RequiredQualifier = QualifierName
// ResultClass = ClassName
// ResultRole = PropertyName
// Role = PropertyName
long queryLength = 1; // Terminating NULL
queryLength += wcslen (WMIXML_QUERY_ASSOCOF) +
wcslen (WMIXML_QUERY_OPENBRACE) +
wcslen (WMIXML_QUERY_CLOSEBRACE) +
wcslen (strObjectPath);
BOOL needWhere = FALSE;
if ((strAssocClass && (0 < wcslen (strAssocClass))) ||
(strResultClass && (0 < wcslen (strResultClass))) ||
(strResultRole && (0 < wcslen (strResultRole))) ||
(strRole && (0 < wcslen (strRole))) ||
(VARIANT_FALSE != bClassesOnly) ||
(VARIANT_FALSE != bSchemaOnly) ||
(strRequiredAssocQualifier && (0 < wcslen (strRequiredAssocQualifier))) ||
(strRequiredQualifier && (0 < wcslen (strRequiredQualifier))))
{
needWhere = TRUE;
queryLength += wcslen (WMIXML_QUERY_WHERE);
}
if (strAssocClass && (0 < wcslen (strAssocClass)))
queryLength += wcslen (WMIXML_QUERY_ASSOCCLASS) +
wcslen (WMIXML_QUERY_EQUALS) +
wcslen (strAssocClass);
if (strResultClass && (0 < wcslen (strResultClass)))
queryLength += wcslen (WMIXML_QUERY_RESCLASS) +
wcslen (WMIXML_QUERY_EQUALS) +
wcslen (strResultClass);
if (strResultRole && (0 < wcslen (strResultRole)))
queryLength += wcslen (WMIXML_QUERY_RESROLE) +
wcslen (WMIXML_QUERY_EQUALS) +
wcslen (strResultRole);
if (strRole && (0 < wcslen (strRole)))
queryLength += wcslen (WMIXML_QUERY_ROLE) +
wcslen (WMIXML_QUERY_EQUALS) +
wcslen (strRole);
if (VARIANT_FALSE != bClassesOnly)
queryLength += wcslen (WMIXML_QUERY_CLASSDEFS);
if (VARIANT_FALSE != bSchemaOnly)
queryLength += wcslen (WMIXML_QUERY_SCHEMAONLY);
if (strRequiredAssocQualifier && (0 < wcslen (strRequiredAssocQualifier)))
queryLength += wcslen (WMIXML_QUERY_REQASSOCQ) +
wcslen (WMIXML_QUERY_EQUALS) +
wcslen (strRequiredAssocQualifier);
if (strRequiredQualifier && (0 < wcslen (strRequiredQualifier)))
queryLength += wcslen (WMIXML_QUERY_REQQUAL) +
wcslen (WMIXML_QUERY_EQUALS) +
wcslen (strRequiredQualifier);
// Allocate the string and fill it in
bsQuery = SysAllocStringLen (WMIXML_QUERY_ASSOCOF, queryLength);
wcscat (bsQuery, WMIXML_QUERY_OPENBRACE);
wcscat (bsQuery, strObjectPath);
wcscat (bsQuery, WMIXML_QUERY_CLOSEBRACE);
if (needWhere)
{
wcscat (bsQuery, WMIXML_QUERY_WHERE);
if (strAssocClass && (0 < wcslen (strAssocClass)))
{
wcscat (bsQuery, WMIXML_QUERY_ASSOCCLASS);
wcscat (bsQuery, WMIXML_QUERY_EQUALS);
wcscat (bsQuery, strAssocClass);
}
if (strResultClass && (0 < wcslen (strResultClass)))
{
wcscat (bsQuery, WMIXML_QUERY_RESCLASS);
wcscat (bsQuery, WMIXML_QUERY_EQUALS);
wcscat (bsQuery, strResultClass);
}
if (strResultRole && (0 < wcslen (strResultRole)))
{
wcscat (bsQuery, WMIXML_QUERY_RESROLE);
wcscat (bsQuery, WMIXML_QUERY_EQUALS);
wcscat (bsQuery, strResultRole);
}
if (strRole && (0 < wcslen (strRole)))
{
wcscat (bsQuery, WMIXML_QUERY_ROLE);
wcscat (bsQuery, WMIXML_QUERY_EQUALS);
wcscat (bsQuery, strRole);
}
if (VARIANT_FALSE != bClassesOnly)
wcscat (bsQuery, WMIXML_QUERY_CLASSDEFS);
if (VARIANT_FALSE != bSchemaOnly)
wcscat (bsQuery, WMIXML_QUERY_SCHEMAONLY);
if (strRequiredAssocQualifier && (0 < wcslen (strRequiredAssocQualifier)))
{
wcscat (bsQuery, WMIXML_QUERY_REQASSOCQ);
wcscat (bsQuery, WMIXML_QUERY_EQUALS);
wcscat (bsQuery, strRequiredAssocQualifier);
}
if (strRequiredQualifier && (0 < wcslen (strRequiredQualifier)))
{
wcscat (bsQuery, WMIXML_QUERY_REQQUAL);
wcscat (bsQuery, WMIXML_QUERY_EQUALS);
wcscat (bsQuery, strRequiredQualifier);
}
}
return bsQuery;
}
//***************************************************************************
//
// BSTR FormatReferencesQuery
//
// Description:
//
// Takes the parameters to an ReferencesOf call and constructs a WQL
// query string from them.
//
// Returns: The constructed WQL query; this must be freed using
// SysFreeString by the caller.
//
// pdispparams the input dispatch parameters
//
//***************************************************************************
BSTR FormatReferencesQuery
(
BSTR strObjectPath,
BSTR strResultClass,
BSTR strRole,
VARIANT_BOOL bClassesOnly,
VARIANT_BOOL bSchemaOnly,
BSTR strRequiredQualifier
)
{
BSTR bsQuery = NULL;
// Get the length of the string:
// references of {SourceObject} where
// ClassDefsOnly
// SchemaOnly
// RequiredQualifier = QualifierName
// ResultClass = ClassName
// Role = PropertyName
long queryLength = 1; // Terminating NULL
queryLength += wcslen (WMIXML_QUERY_REFOF) +
wcslen (WMIXML_QUERY_OPENBRACE) +
wcslen (WMIXML_QUERY_CLOSEBRACE) +
wcslen (strObjectPath);
BOOL needWhere = FALSE;
if ((strResultClass && (0 < wcslen (strResultClass))) ||
(strRole && (0 < wcslen (strRole))) ||
(VARIANT_FALSE != bClassesOnly) ||
(VARIANT_FALSE != bSchemaOnly) ||
(strRequiredQualifier && (0 < wcslen (strRequiredQualifier))))
{
needWhere = TRUE;
queryLength += wcslen (WMIXML_QUERY_WHERE);
}
if (strResultClass && (0 < wcslen (strResultClass)))
queryLength += wcslen (WMIXML_QUERY_RESCLASS) +
wcslen (WMIXML_QUERY_EQUALS) +
wcslen (strResultClass);
if (strRole && (0 < wcslen (strRole)))
queryLength += wcslen (WMIXML_QUERY_ROLE) +
wcslen (WMIXML_QUERY_EQUALS) +
wcslen (strRole);
if (VARIANT_FALSE != bClassesOnly)
queryLength += wcslen (WMIXML_QUERY_CLASSDEFS);
if (VARIANT_FALSE != bSchemaOnly)
queryLength += wcslen (WMIXML_QUERY_SCHEMAONLY);
if (strRequiredQualifier && (0 < wcslen (strRequiredQualifier)))
queryLength += wcslen (WMIXML_QUERY_REQQUAL) +
wcslen (WMIXML_QUERY_EQUALS) +
wcslen (strRequiredQualifier);
// Allocate the string and fill it in
bsQuery = SysAllocStringLen (WMIXML_QUERY_REFOF, queryLength);
wcscat (bsQuery, WMIXML_QUERY_OPENBRACE);
wcscat (bsQuery, strObjectPath);
wcscat (bsQuery, WMIXML_QUERY_CLOSEBRACE);
if (needWhere)
{
wcscat (bsQuery, WMIXML_QUERY_WHERE);
if (strResultClass && (0 < wcslen (strResultClass)))
{
wcscat (bsQuery, WMIXML_QUERY_RESCLASS);
wcscat (bsQuery, WMIXML_QUERY_EQUALS);
wcscat (bsQuery, strResultClass);
}
if (strRole && (0 < wcslen (strRole)))
{
wcscat (bsQuery, WMIXML_QUERY_ROLE);
wcscat (bsQuery, WMIXML_QUERY_EQUALS);
wcscat (bsQuery, strRole);
}
if (VARIANT_FALSE != bClassesOnly)
wcscat (bsQuery, WMIXML_QUERY_CLASSDEFS);
if (VARIANT_FALSE != bSchemaOnly)
wcscat (bsQuery, WMIXML_QUERY_SCHEMAONLY);
if (strRequiredQualifier && (0 < wcslen (strRequiredQualifier)))
{
wcscat (bsQuery, WMIXML_QUERY_REQQUAL);
wcscat (bsQuery, WMIXML_QUERY_EQUALS);
wcscat (bsQuery, strRequiredQualifier);
}
}
return bsQuery;
}
BOOL CXMLTranslator::TransformQuery (BSTR *pbsQueryString) // , bool &bGenusAdded, bool&bClassAdded)
{
return FALSE;
/*
bGenusAdded = true;
bClassAdded = true;
BOOL result = FALSE;
// The problem we're facing here is the case where projected queries are used
// In this case, what happens is that the projection list might be missing one of the
// following system properties that are required by us for generating VALUE.OBJECTs:
// __GENUS : We need this to decide whether to generate CLASS or INSTANCE tag
// __CLASS : We need this for the NAME attribute of a CLASS or INSTANCE
// __SUPERCLASS : We need this for a CLASS tag. But it is not mandatory
// If we are doing a select, make sure we add in __CLASS, __GENUS and __SUPERCLASS
// However, we also face the problem, that these might or might not have been present in the
// list of properties in the projection. If they were present, then we're fine. Otherwise,
// we need to remove them in the final conversion to XML
IWbemQuery *pQuery = NULL;
HRESULT hr = CoCreateInstance(CLSID_WbemQuery, 0, CLSCTX_INPROC_SERVER,
IID_IWbemQuery, (LPVOID *) &pQuery);
if(SUCCEEDED(hr))
{
// Parse it to get the properties in the projection list
if(SUCCEEDED(hr = pQuery->SetLanguageFeatures(0, sizeof(uFeatures)/sizeof(ULONG), uFeatures)))
{
if(SUCCEEDED(hr = pQuery->Parse(L"SQL", *pbsQueryString, 0)))
{
SWbemRpnEncodedQuery *pRpn = NULL;
if(SUCCEEDED(hr = pQuery->GetAnalysis(
WMIQ_ANALYSIS_RPN_SEQUENCE,
0,
(LPVOID *) &pRpn
)))
{
// Go thru the list, looking for __GENUS and __CLASS
for(ULONG i=0; i<pRpn->m_uSelectListSize; i++)
{
SWbemQueryQualifiedName *p = pRpn->m_ppSelectList[i];
if(_wcsicmp(p->m_ppszNameList[0], L"*") == 0)
{
bClassAdded = false;
bGenusAdded = false;
break;
}
else if(_wcsicmp(p->m_ppszNameList[0], L"__GENUS") == 0)
bGenusAdded = false;
else if(_wcsicmp(p->m_ppszNameList[0], L"__CLASS") == 0)
bClassAdded = false;
}
pQuery->FreeMemory(pRpn);
}
}
}
pQuery->Release();
}
// Now we know whether __GENUS and __CLASS occured.
if(bGenusAdded && bClassAdded)
result = AddClause(L"select __GENUS, __CLASS, ");
else if(bGenusAdded)
result = AddClause(L"select __GENUS, ");
else if(bClassAdded)
result = AddClause(L"select __CLASS, ");
return result;
*/
}
BOOL AddClause(BSTR *pbsQueryString, LPCWSTR pszClause)
{
BOOL result = FALSE;
// RAJESHR - We're currently Hand-inserting clauses into the query.
// We should be really having an Unparse() in Core team's Query parser
int i = 0;
int len = wcslen (*pbsQueryString);
// Move to the first space past the "select" token
while ((i < len) && iswspace ((*pbsQueryString) [i]))
i++;
// See if the token was really "select"
if ((i < len) && (0 == _wcsnicmp (L"select", &((*pbsQueryString) [i]), wcslen(L"select"))))
{
i += wcslen (L"select");
// Move past the white spaces after "select"
while ((i < len) && iswspace ((*pbsQueryString) [i]))
i++;
// Need to add in the system properties
WCHAR *pNewQuery = NULL;
if(pNewQuery = new WCHAR [wcslen (&((*pbsQueryString) [i])) +
wcslen (pszClause) + 1])
{
wcscpy (pNewQuery, pszClause);
wcscat (pNewQuery, &((*pbsQueryString) [i]));
*pbsQueryString = NULL;
if(*pbsQueryString = SysAllocString (pNewQuery))
result = TRUE;
delete [] pNewQuery;
}
}
return result;
}