You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2612 lines
70 KiB
2612 lines
70 KiB
//***************************************************************************
|
|
//
|
|
// (c) 1998 by Microsoft Corporation
|
|
//
|
|
// WBEM2XML.CPP
|
|
//
|
|
// alanbos 18-Feb-98 Created.
|
|
//
|
|
// The WBEM -> XML translator
|
|
//
|
|
//***************************************************************************
|
|
|
|
#include "precomp.h"
|
|
#include <wbemidl.h>
|
|
|
|
#include <genlex.h>
|
|
#include <opathlex.h>
|
|
#include <objpath.h>
|
|
|
|
#include "wmiconv.h"
|
|
#include "wmi2xml.h"
|
|
|
|
// This is the set of the names of properties that the control
|
|
// looks for in an IWbemContext object for modifying its output
|
|
const LPCWSTR CWmiToXml::s_wmiToXmlArgs[] =
|
|
{
|
|
L"AllowWMIExtensions", // VT_BOOL - self-explanatory
|
|
L"PathLevel", // VT_I4 see typedef enum PathLevel in wmi2xml.h
|
|
L"IncludeQualifiers", // VT_BOOL - self-explanatory
|
|
L"IncludeClassOrigin", // VT_BOOL - self-explanatory
|
|
L"LocalOnly", // VT_BOOL - local elements (methods, properties, qualifiers) are mapped.
|
|
L"ExcludeSystemProperties", // VT_BOOL - Excludes any WMI System Properties
|
|
};
|
|
|
|
|
|
static OLECHAR *CDATASTART = OLESTR("<![CDATA[");
|
|
static OLECHAR *CDATAEND = OLESTR("]]>");
|
|
static OLECHAR *AMPERSAND = OLESTR("&");
|
|
static OLECHAR *LEFTCHEVRON = OLESTR("<");
|
|
static OLECHAR *RIGHTCHEVRON = OLESTR(">");
|
|
static BYTE XMLNEWLINE [] = { 0x0D, 0x00, 0x0A, 0x00 };
|
|
extern long g_cObj;
|
|
|
|
CWmiToXml::CWmiToXml()
|
|
{
|
|
m_cRef = 0;
|
|
m_iPathLevel = pathLevelAnonymous; // RAJESHR - Is this a good default
|
|
m_bAllowWMIExtensions = VARIANT_TRUE;
|
|
m_bLocalOnly = VARIANT_FALSE; // RAJESHR - Change this when core team allows us to set __RELPATH
|
|
m_iQualifierFilter = wmiXMLQualifierFilterNone;
|
|
m_iClassOriginFilter = wmiXMLClassOriginFilterAll;
|
|
m_bExcludeSystemProperties = VARIANT_FALSE;
|
|
InterlockedIncrement(&g_cObj);
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CWmiToXml::~CWmiToXml
|
|
//
|
|
// DESCRIPTION:
|
|
//
|
|
// Destructor.
|
|
//
|
|
//***************************************************************************
|
|
|
|
CWmiToXml::~CWmiToXml(void)
|
|
{
|
|
InterlockedDecrement(&g_cObj);
|
|
}
|
|
|
|
//***************************************************************************
|
|
// HRESULT CWmiToXml::QueryInterface
|
|
// long CWmiToXml::AddRef
|
|
// long CWmiToXml::Release
|
|
//
|
|
// DESCRIPTION:
|
|
//
|
|
// Standard Com IUNKNOWN functions.
|
|
//
|
|
//***************************************************************************
|
|
|
|
STDMETHODIMP CWmiToXml::QueryInterface (
|
|
|
|
IN REFIID riid,
|
|
OUT LPVOID *ppv
|
|
)
|
|
{
|
|
*ppv=NULL;
|
|
|
|
if (IID_IUnknown==riid)
|
|
*ppv = reinterpret_cast<IUnknown*>(this);
|
|
else if (IID_IWbemXMLConvertor==riid)
|
|
*ppv = reinterpret_cast<IWbemXMLConvertor*>(this);
|
|
|
|
if (NULL!=*ppv)
|
|
{
|
|
((LPUNKNOWN)*ppv)->AddRef();
|
|
return NOERROR;
|
|
}
|
|
|
|
return ResultFromScode(E_NOINTERFACE);
|
|
}
|
|
|
|
STDMETHODIMP_(ULONG) CWmiToXml::AddRef(void)
|
|
{
|
|
InterlockedIncrement(&m_cRef);
|
|
return m_cRef;
|
|
}
|
|
|
|
STDMETHODIMP_(ULONG) CWmiToXml::Release(void)
|
|
{
|
|
InterlockedDecrement(&m_cRef);
|
|
if (0L!=m_cRef)
|
|
return m_cRef;
|
|
delete this;
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*
|
|
* This function takes in an IWbemClassObject that represents a Class and
|
|
* produces a <CLASS> element in the outputstream
|
|
*/
|
|
STDMETHODIMP CWmiToXml::MapClass (IStream *pOutputStream, IWbemClassObject *pObject, IWbemQualifierSet *pQualSet, BSTR *ppPropertyList, DWORD dwNumProperties, BSTR strClassBasis)
|
|
{
|
|
HRESULT hr = WBEM_E_FAILED;
|
|
|
|
long flav = 0;
|
|
VARIANT var;
|
|
|
|
// Write the CLASS tag and its attributes
|
|
//===========================================
|
|
WRITEBSTR( OLESTR("<CLASS NAME=\""))
|
|
|
|
// Write the CLASSNAME
|
|
VariantInit (&var);
|
|
if (WBEM_S_NO_ERROR == pObject->Get(L"__CLASS", 0, &var, NULL, &flav))
|
|
{
|
|
if ((VT_BSTR == var.vt) && (NULL != var.bstrVal) && (wcslen (var.bstrVal) > 0))
|
|
WRITEBSTR( var.bstrVal)
|
|
}
|
|
VariantClear (&var);
|
|
WRITEBSTR( OLESTR("\""))
|
|
|
|
// Write the SUPERCLASS if specified
|
|
VariantInit (&var);
|
|
if (WBEM_S_NO_ERROR == pObject->Get(L"__SUPERCLASS", 0, &var, NULL, &flav))
|
|
{
|
|
if ((VT_BSTR == var.vt) && (NULL != var.bstrVal) && (wcslen (var.bstrVal) > 0))
|
|
{
|
|
WRITEBSTR( OLESTR(" SUPERCLASS=\""))
|
|
WRITEBSTR( var.bstrVal)
|
|
WRITEBSTR( OLESTR("\""))
|
|
}
|
|
}
|
|
VariantClear (&var);
|
|
WRITEBSTR( OLESTR(">"))
|
|
WRITENEWLINE
|
|
|
|
// Map the Qualifiers of the class
|
|
if (pQualSet)
|
|
hr = MapQualifiers (pOutputStream, pQualSet);
|
|
else
|
|
hr = S_OK;
|
|
|
|
// Map the Properties
|
|
if (SUCCEEDED(hr))
|
|
hr = MapProperties(pOutputStream, pObject, ppPropertyList, dwNumProperties, strClassBasis, true);
|
|
|
|
// Map the Methods
|
|
if (SUCCEEDED(hr))
|
|
hr = MapMethods (pOutputStream, pObject);
|
|
|
|
// Terminate the CLASS element
|
|
WRITEBSTR( OLESTR("</CLASS>"))
|
|
WRITENEWLINE
|
|
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CWmiToXml::MapClassPath (IStream *pOutputStream, ParsedObjectPath *pParsedPath)
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
WRITEBSTR( OLESTR("<CLASSPATH>"))
|
|
WRITENEWLINE
|
|
if(SUCCEEDED(hr = MapNamespacePath (pOutputStream, pParsedPath)))
|
|
{
|
|
WRITENEWLINE
|
|
hr = MapClassName (pOutputStream, pParsedPath->m_pClass);
|
|
}
|
|
WRITEBSTR( OLESTR("</CLASSPATH>"))
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CWmiToXml::MapLocalClassPath (IStream *pOutputStream, ParsedObjectPath *pParsedPath)
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
WRITEBSTR( OLESTR("<LOCALCLASSPATH>"))
|
|
WRITENEWLINE
|
|
if(SUCCEEDED(hr = MapLocalNamespacePath (pOutputStream, pParsedPath)))
|
|
{
|
|
WRITENEWLINE
|
|
hr = MapClassName (pOutputStream, pParsedPath->m_pClass);
|
|
}
|
|
WRITEBSTR( OLESTR("</LOCALCLASSPATH>"))
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CWmiToXml::MapClassName (IStream *pOutputStream, BSTR bsClassName)
|
|
{
|
|
WRITEBSTR( OLESTR("<CLASSNAME NAME=\""))
|
|
WRITEBSTR( bsClassName)
|
|
WRITEBSTR( OLESTR("\"/>"))
|
|
return S_OK;
|
|
}
|
|
|
|
/*
|
|
* This function takes in an IWbemClassObject that represents an Instance and
|
|
* produces an <INSTANCE> element in the outputstream
|
|
*/
|
|
STDMETHODIMP CWmiToXml::MapInstance (IStream *pOutputStream, IWbemClassObject *pObject, IWbemQualifierSet *pQualSet, BSTR *ppPropertyList, DWORD dwNumProperties, BSTR strClassBasis)
|
|
{
|
|
HRESULT hr = WBEM_E_FAILED;
|
|
|
|
// Write the beginning of the INSTANCE Tag and its attributes
|
|
//===========================================================
|
|
WRITEBSTR( OLESTR("<INSTANCE CLASSNAME=\""))
|
|
// Write the CLASSNAME
|
|
long flav = 0;
|
|
VARIANT var;
|
|
VariantInit (&var);
|
|
if (WBEM_S_NO_ERROR == pObject->Get(L"__CLASS", 0, &var, NULL, &flav))
|
|
{
|
|
if ((VT_BSTR == var.vt) && (NULL != var.bstrVal) && (wcslen (var.bstrVal) > 0))
|
|
{
|
|
WRITEBSTR( var.bstrVal)
|
|
WRITEBSTR( OLESTR("\">"))
|
|
WRITENEWLINE
|
|
}
|
|
}
|
|
VariantClear (&var);
|
|
|
|
// Map Instance Qualifiers if any
|
|
if (pQualSet)
|
|
hr = MapQualifiers (pOutputStream, pQualSet);
|
|
else
|
|
hr = S_OK;
|
|
|
|
// Map the properties of the instance
|
|
if(SUCCEEDED(hr))
|
|
hr = MapProperties (pOutputStream, pObject, ppPropertyList, dwNumProperties, strClassBasis, false);
|
|
|
|
// Terminate the INSTANCE element
|
|
WRITEBSTR( OLESTR("</INSTANCE>"))
|
|
WRITENEWLINE
|
|
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CWmiToXml::MapInstancePath (IStream *pOutputStream, ParsedObjectPath *pParsedPath)
|
|
{
|
|
WRITEBSTR( OLESTR("<INSTANCEPATH>"))
|
|
WRITENEWLINE
|
|
HRESULT hr = E_FAIL;
|
|
if(SUCCEEDED(hr = MapNamespacePath (pOutputStream, pParsedPath)))
|
|
{
|
|
WRITENEWLINE
|
|
hr = MapInstanceName (pOutputStream, pParsedPath);
|
|
WRITENEWLINE
|
|
}
|
|
WRITEBSTR( OLESTR("</INSTANCEPATH>"))
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CWmiToXml::MapLocalInstancePath (IStream *pOutputStream, ParsedObjectPath *pParsedPath)
|
|
{
|
|
WRITEBSTR( OLESTR("<LOCALINSTANCEPATH>"))
|
|
WRITENEWLINE
|
|
HRESULT hr = E_FAIL;
|
|
if(SUCCEEDED(hr = MapLocalNamespacePath (pOutputStream, pParsedPath)))
|
|
{
|
|
WRITENEWLINE
|
|
hr = MapInstanceName (pOutputStream, pParsedPath);
|
|
WRITENEWLINE
|
|
}
|
|
WRITEBSTR( OLESTR("</LOCALINSTANCEPATH>"))
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CWmiToXml::MapInstanceName (IStream *pOutputStream, ParsedObjectPath *pParsedPath)
|
|
{
|
|
WRITEBSTR( OLESTR("<INSTANCENAME CLASSNAME=\""))
|
|
WRITEBSTR( pParsedPath->m_pClass)
|
|
WRITEBSTR( OLESTR("\">"))
|
|
WRITENEWLINE
|
|
|
|
// Now write the key bindings - only if not singleton
|
|
if (!(pParsedPath->m_bSingletonObj))
|
|
{
|
|
if ((1 == pParsedPath->m_dwNumKeys) &&
|
|
!((pParsedPath->m_paKeys [0])->m_pName))
|
|
{
|
|
// Use the short form
|
|
WRITENEWLINE
|
|
MapKeyValue (pOutputStream, (pParsedPath->m_paKeys [0])->m_vValue);
|
|
WRITENEWLINE
|
|
}
|
|
else
|
|
{
|
|
// Write each key-value binding
|
|
//=============================
|
|
for (DWORD numKey = 0; numKey < pParsedPath->m_dwNumKeys; numKey++)
|
|
{
|
|
WRITEBSTR( OLESTR("<KEYBINDING "))
|
|
|
|
// Write the key name
|
|
WRITEBSTR( OLESTR(" NAME=\""))
|
|
WRITEBSTR( (pParsedPath->m_paKeys [numKey])->m_pName)
|
|
WRITEBSTR( OLESTR("\">"))
|
|
WRITENEWLINE
|
|
|
|
// Write the key value
|
|
MapKeyValue (pOutputStream, (pParsedPath->m_paKeys [numKey])->m_vValue);
|
|
WRITENEWLINE
|
|
|
|
WRITEBSTR( OLESTR("</KEYBINDING>"))
|
|
WRITENEWLINE
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Nothing to be done here, since the spec says that
|
|
// INSTANCENAMEs without any keybindings are assumed to be singleton instances
|
|
}
|
|
|
|
WRITEBSTR( OLESTR("</INSTANCENAME>"))
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP CWmiToXml::MapNamespacePath (IStream *pOutputStream, BSTR bsNamespacePath)
|
|
{
|
|
CObjectPathParser pathParser (e_ParserAcceptRelativeNamespace);
|
|
ParsedObjectPath *pParsedPath = NULL;
|
|
pathParser.Parse (bsNamespacePath, &pParsedPath) ;
|
|
|
|
HRESULT hr = E_FAIL;
|
|
if (pParsedPath)
|
|
{
|
|
hr = MapNamespacePath (pOutputStream, pParsedPath);
|
|
pathParser.Free(pParsedPath);
|
|
}
|
|
else
|
|
hr = WBEM_E_INVALID_SYNTAX;
|
|
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CWmiToXml::MapNamespacePath (IStream *pOutputStream, ParsedObjectPath *pParsedPath)
|
|
{
|
|
WRITEBSTR( OLESTR("<NAMESPACEPATH>"))
|
|
WRITENEWLINE
|
|
WRITEBSTR( OLESTR("<HOST>"))
|
|
|
|
if (pParsedPath->m_pServer)
|
|
WRITEWSTR( pParsedPath->m_pServer)
|
|
else
|
|
WRITEBSTR( OLESTR("."))
|
|
|
|
WRITEBSTR( OLESTR("</HOST>"))
|
|
WRITENEWLINE
|
|
|
|
// Map the local namespaces
|
|
HRESULT hr = MapLocalNamespacePath (pOutputStream, pParsedPath);
|
|
|
|
WRITEBSTR( OLESTR("</NAMESPACEPATH>"))
|
|
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CWmiToXml::MapLocalNamespacePath (IStream *pOutputStream, BSTR bsNamespacePath)
|
|
{
|
|
CObjectPathParser pathParser (e_ParserAcceptRelativeNamespace);
|
|
ParsedObjectPath *pParsedPath = NULL;
|
|
pathParser.Parse (bsNamespacePath, &pParsedPath) ;
|
|
|
|
HRESULT hr = E_FAIL;
|
|
if (pParsedPath)
|
|
{
|
|
hr = MapLocalNamespacePath (pOutputStream, pParsedPath);
|
|
pathParser.Free(pParsedPath);
|
|
}
|
|
else
|
|
hr = E_FAIL;
|
|
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CWmiToXml::MapLocalNamespacePath (IStream *pOutputStream, ParsedObjectPath *pObjectPath)
|
|
{
|
|
WRITEBSTR( OLESTR("<LOCALNAMESPACEPATH>"))
|
|
WRITENEWLINE
|
|
|
|
// Map each of the namespace components
|
|
for (DWORD dwIndex = 0; dwIndex < pObjectPath->m_dwNumNamespaces; dwIndex++)
|
|
{
|
|
WRITEBSTR( OLESTR("<NAMESPACE NAME=\""))
|
|
WRITEWSTR( pObjectPath->m_paNamespaces [dwIndex])
|
|
WRITEBSTR( OLESTR("\"/>"))
|
|
WRITENEWLINE
|
|
}
|
|
|
|
WRITEBSTR( OLESTR("</LOCALNAMESPACEPATH>"))
|
|
|
|
return WBEM_S_NO_ERROR;
|
|
}
|
|
|
|
STDMETHODIMP CWmiToXml::MapReferenceProperty (IStream *pOutputStream, IWbemClassObject *pObject, BSTR name, VARIANT &var, bool isArray, long flavor, bool bIsClass)
|
|
{
|
|
// CIM does not allow array references, only scalar references
|
|
if(isArray && !m_bAllowWMIExtensions)
|
|
return S_OK;
|
|
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
|
|
IWbemQualifierSet *pQualSet = NULL;
|
|
if (WBEM_S_NO_ERROR == pObject->GetPropertyQualifierSet (name, &pQualSet))
|
|
{
|
|
// The property name
|
|
if (isArray)
|
|
WRITEBSTR( OLESTR("<PROPERTY.REFARRAY NAME=\""))
|
|
else
|
|
WRITEBSTR( OLESTR("<PROPERTY.REFERENCE NAME=\""))
|
|
|
|
// The property name
|
|
WRITEBSTR( name)
|
|
WRITEBSTR( OLESTR("\""))
|
|
|
|
// The originating class of this property
|
|
BSTR propertyOrigin = NULL;
|
|
|
|
if (WBEM_S_NO_ERROR == pObject->GetPropertyOrigin (name, &propertyOrigin))
|
|
{
|
|
MapClassOrigin (pOutputStream, propertyOrigin, bIsClass);
|
|
SysFreeString(propertyOrigin);
|
|
hr = S_OK;
|
|
}
|
|
|
|
if(SUCCEEDED(hr))
|
|
MapLocal (pOutputStream, flavor);
|
|
|
|
// The strong class of this property
|
|
if(SUCCEEDED(hr))
|
|
MapStrongType (pOutputStream, pQualSet);
|
|
|
|
// Size of array
|
|
if(SUCCEEDED(hr) && isArray)
|
|
MapArraySize (pOutputStream, pQualSet);
|
|
|
|
WRITEBSTR( OLESTR(">"))
|
|
WRITENEWLINE
|
|
|
|
// Map the qualifiers
|
|
if(SUCCEEDED(hr))
|
|
hr = MapQualifiers (pOutputStream, pQualSet);
|
|
|
|
if(SUCCEEDED(hr))
|
|
hr = MapReferenceValue (pOutputStream, isArray, var);
|
|
|
|
if (isArray)
|
|
WRITEBSTR( OLESTR("</PROPERTY.REFARRAY>"))
|
|
else
|
|
WRITEBSTR( OLESTR("</PROPERTY.REFERENCE>"))
|
|
pQualSet->Release ();
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CWmiToXml::IsReference
|
|
//
|
|
// DESCRIPTION:
|
|
//
|
|
// The purpose of this function is to examine a single
|
|
// VARIANT value and determine whether it represents a
|
|
// reference or not.
|
|
//
|
|
// This is required because when mapping from a reference
|
|
// property value we may encounter nested references within
|
|
// the object path. Unfortunately the object path syntax
|
|
// is such that we cannot be certain whether a key value
|
|
// represents a reference or a string, datetime or char
|
|
// property. (This is because a textual object path does
|
|
// not contain as much information as its XML equivalent.)
|
|
//
|
|
// This function performs a heuristic test on the value to
|
|
// determine whether it is a reference.
|
|
//
|
|
//***************************************************************************
|
|
|
|
bool CWmiToXml::IsReference (VARIANT &var, ParsedObjectPath **ppObjectPath)
|
|
{
|
|
ParsedObjectPath *pObjectPath = NULL;
|
|
*ppObjectPath = NULL;
|
|
bool isValidPath = false;
|
|
|
|
// RAJESHR - could get the class of which this is a property value
|
|
// and retrieve the type of the current key property - that would
|
|
// be the authoritative answer but it doesn't come cheap.
|
|
|
|
if ((VT_BSTR == var.vt) && (NULL != var.bstrVal) && (wcslen (var.bstrVal) > 0))
|
|
{
|
|
|
|
// Parse the object path
|
|
CObjectPathParser parser (e_ParserAcceptRelativeNamespace);
|
|
BOOL status = parser.Parse (var.bstrVal, &pObjectPath);
|
|
|
|
if ((0 == status) && pObjectPath)
|
|
{
|
|
// If it's an instance path we should be OK
|
|
if (pObjectPath->IsInstance ())
|
|
isValidPath = true;
|
|
else if (pObjectPath->IsClass ())
|
|
{
|
|
// Hmmm - could be a classpath. If we have a server
|
|
// and some namespaces that would be a lot better
|
|
|
|
if (pObjectPath->m_pServer && (0 < pObjectPath->m_dwNumNamespaces))
|
|
{
|
|
// RAJESHR - At this point we could assume that it is a reference
|
|
// However, we've found a case in PCHealth where they do a
|
|
// select * from Win32_ProgramGroup and it so happens that
|
|
// one of the properties has a value "ntdev\rajeshr:Accessories"
|
|
// which is CIM_STRING but actually matches a WMI class path
|
|
// So, we need to try to connect ot this machine or namespace here
|
|
// to check whether it is a classpath.
|
|
|
|
}
|
|
else
|
|
{
|
|
// A potential local class path
|
|
// RAJESHR - try grabbing the class to see if it exists in
|
|
// the current namespace.
|
|
}
|
|
}
|
|
}
|
|
// Apply one more heuristic - see whether it begins with "umi:"
|
|
else
|
|
{
|
|
if(_wcsnicmp(var.bstrVal, L"umi:", wcslen(L"umi:")) == 0)
|
|
isValidPath = true;
|
|
}
|
|
|
|
if (isValidPath)
|
|
*ppObjectPath = pObjectPath;
|
|
else
|
|
{
|
|
// Reject for now - too ambiguous
|
|
parser.Free(pObjectPath);
|
|
pObjectPath = NULL;
|
|
}
|
|
}
|
|
|
|
return isValidPath;
|
|
}
|
|
|
|
HRESULT CWmiToXml::MapReferenceValue (IStream *pOutputStream, bool isArray, VARIANT &var)
|
|
{
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
|
|
if (VT_NULL == var.vt)
|
|
return WBEM_S_NO_ERROR;
|
|
|
|
if (isArray)
|
|
{
|
|
long uBound = 0;
|
|
if (FAILED(SafeArrayGetUBound (var.parray, 1, &uBound)))
|
|
return WBEM_E_FAILED;
|
|
|
|
WRITEBSTR( OLESTR("<VALUE.REFARRAY>"))
|
|
for (long i = 0; i<=uBound; i++)
|
|
{
|
|
BSTR pNextElement = NULL;
|
|
if(SUCCEEDED(hr = SafeArrayGetElement(var.parray, (LONG *)&i, (LPVOID )&pNextElement )))
|
|
{
|
|
// Map the value - this will be a classpath or instancepath
|
|
if ((NULL != pNextElement) && (wcslen (pNextElement) > 0))
|
|
{
|
|
// Parse the object path
|
|
// We have 2 possibilities here
|
|
// 1. The path is a Nova style path in which case it can be transformed into
|
|
// a DMTF style VALUE.REFERENCE
|
|
// 2. It is a Whistler style scoped path or an UMI path. In this case,
|
|
// we have to transform it into a VALUE element (inside a VALUE.REFERENCE element)
|
|
// with the exact string representation of the path
|
|
// The second vase is indicated it the parsing fails.
|
|
CObjectPathParser parser (e_ParserAcceptRelativeNamespace);
|
|
ParsedObjectPath *pObjectPath = NULL;
|
|
BOOL status = parser.Parse (pNextElement, &pObjectPath) ;
|
|
|
|
// pObjectPath might be NULL here, in which case it falls under category 2 above
|
|
MapReferenceValue (pOutputStream, pObjectPath, pNextElement);
|
|
|
|
if (pObjectPath)
|
|
parser.Free(pObjectPath);
|
|
}
|
|
|
|
SysFreeString(pNextElement);
|
|
}
|
|
}
|
|
WRITEBSTR( OLESTR("</VALUE.REFARRAY>"))
|
|
}
|
|
else
|
|
{
|
|
// Map the value - this will be a classpath or instancepath
|
|
if ((VT_BSTR == var.vt) && (NULL != var.bstrVal) && (wcslen (var.bstrVal) > 0))
|
|
{
|
|
// Parse the object path
|
|
CObjectPathParser parser (e_ParserAcceptRelativeNamespace);
|
|
ParsedObjectPath *pObjectPath = NULL;
|
|
BOOL status = parser.Parse (var.bstrVal, &pObjectPath) ;
|
|
|
|
// We have 2 possibilities here
|
|
// 1. The path is a Nova style path in which case it can be transformed into
|
|
// a DMTF style VALUE.REFERENCE
|
|
// 2. It is a Whistler style scoped path or an UMI path. In this case,
|
|
// we have to transform it into a VALUE element (inside a VALUE.REFERENCE element)
|
|
// with the exact string representation of the path
|
|
// The second vase is indicated it the parsing fails.
|
|
MapReferenceValue (pOutputStream, pObjectPath, var.bstrVal);
|
|
|
|
if (pObjectPath)
|
|
parser.Free(pObjectPath);
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
// This function maps a reference value to XML
|
|
// We have 2 possibilities for the path in the reference value :
|
|
// 1. The path is a Nova style path in which case it can be transformed into
|
|
// a DMTF style VALUE.REFERENCE
|
|
// 2. It is a Whistler style scoped path or an UMI path. In this case,
|
|
// we have to transform it into a VALUE element (inside a VALUE.REFERENCE element)
|
|
// with the exact string representation of the path
|
|
// The second vase is indicated by a NULL value for pObjectPath, in which case, we just
|
|
// use the contents of strPath
|
|
void CWmiToXml::MapReferenceValue (IStream *pOutputStream, ParsedObjectPath *pObjectPath, BSTR strPath)
|
|
{
|
|
WRITEBSTR( OLESTR("<VALUE.REFERENCE>"))
|
|
WRITENEWLINE
|
|
|
|
// Is it a Nova-style or DMTF style path?
|
|
if(pObjectPath)
|
|
{
|
|
BOOL bIsAbsolutePath = (NULL != pObjectPath->m_pServer);
|
|
BOOL bIsRelativePath = FALSE;
|
|
|
|
if (!bIsAbsolutePath)
|
|
bIsRelativePath = (0 < pObjectPath->m_dwNumNamespaces);
|
|
|
|
// Is this is a class or is it an instance?
|
|
if (pObjectPath->IsClass ())
|
|
{
|
|
if (bIsAbsolutePath)
|
|
MapClassPath (pOutputStream, pObjectPath);
|
|
else if (bIsRelativePath)
|
|
MapLocalClassPath (pOutputStream, pObjectPath);
|
|
else
|
|
MapClassName (pOutputStream, pObjectPath->m_pClass);
|
|
}
|
|
else if (pObjectPath->IsInstance ())
|
|
{
|
|
if (bIsAbsolutePath)
|
|
MapInstancePath (pOutputStream, pObjectPath);
|
|
else if (bIsRelativePath)
|
|
MapLocalInstancePath (pOutputStream, pObjectPath);
|
|
else
|
|
MapInstanceName (pOutputStream, pObjectPath);
|
|
}
|
|
}
|
|
else // Ugh it is a Whistler or WMI Path
|
|
{
|
|
WRITEBSTR( OLESTR("<VALUE>"))
|
|
MapStringValue(pOutputStream, strPath);
|
|
WRITEBSTR( OLESTR("</VALUE>"))
|
|
}
|
|
|
|
WRITENEWLINE
|
|
WRITEBSTR( OLESTR("</VALUE.REFERENCE>"))
|
|
}
|
|
|
|
STDMETHODIMP CWmiToXml::MapQualifiers (IStream *pOutputStream,
|
|
IWbemQualifierSet *pQualSet, IWbemQualifierSet *pQualSet2)
|
|
{
|
|
if (wmiXMLQualifierFilterNone != m_iQualifierFilter)
|
|
{
|
|
// Map the requested filter to the flags value - default is ALL
|
|
LONG lFlags = 0;
|
|
if (wmiXMLQualifierFilterLocal == m_iQualifierFilter)
|
|
lFlags = WBEM_FLAG_LOCAL_ONLY;
|
|
else if (wmiXMLQualifierFilterPropagated == m_iQualifierFilter)
|
|
lFlags = WBEM_FLAG_PROPAGATED_ONLY;
|
|
else if (wmiXMLQualifierFilterAll == m_iQualifierFilter)
|
|
{
|
|
if(m_bLocalOnly == VARIANT_TRUE)
|
|
lFlags = WBEM_FLAG_LOCAL_ONLY;
|
|
// Else you get all qualifiers
|
|
}
|
|
|
|
pQualSet->BeginEnumeration (lFlags);
|
|
|
|
VARIANT var;
|
|
VariantInit (&var);
|
|
long flavor = 0;
|
|
BSTR name = NULL;
|
|
|
|
while (WBEM_S_NO_ERROR == pQualSet->Next (0, &name, &var, &flavor))
|
|
{
|
|
MapQualifier (pOutputStream, name, flavor, var);
|
|
SysFreeString (name);
|
|
name = NULL;
|
|
VariantClear (&var);
|
|
}
|
|
|
|
pQualSet->EndEnumeration ();
|
|
|
|
// Now check the subsiduary set for any qualifiers not in the first set
|
|
if (pQualSet2)
|
|
{
|
|
pQualSet2->BeginEnumeration (lFlags);
|
|
|
|
while (WBEM_S_NO_ERROR == pQualSet2->Next (0, &name, &var, &flavor))
|
|
{
|
|
// Is this qualifier in the primary set?
|
|
if (WBEM_E_NOT_FOUND == pQualSet->Get (name, 0, NULL, NULL))
|
|
MapQualifier (pOutputStream, name, flavor, var);
|
|
|
|
SysFreeString (name);
|
|
name = NULL;
|
|
VariantClear (&var);
|
|
}
|
|
|
|
pQualSet2->EndEnumeration ();
|
|
}
|
|
}
|
|
|
|
return WBEM_S_NO_ERROR;
|
|
}
|
|
|
|
void CWmiToXml::MapLocal (IStream *pOutputStream, long flavor)
|
|
{
|
|
// default is FALSE
|
|
if (WBEM_FLAVOR_ORIGIN_PROPAGATED == (WBEM_FLAVOR_MASK_ORIGIN & flavor))
|
|
WRITEBSTR( OLESTR(" PROPAGATED=\"true\""))
|
|
}
|
|
|
|
STDMETHODIMP CWmiToXml::MapQualifier (IStream *pOutputStream, BSTR name, long flavor, VARIANT &var)
|
|
{
|
|
// The qualifier name
|
|
WRITEBSTR( OLESTR("<QUALIFIER NAME=\""))
|
|
WRITEBSTR( name)
|
|
WRITEBSTR( OLESTR("\""))
|
|
MapLocal (pOutputStream, flavor);
|
|
|
|
// The qualifier CIM type
|
|
WRITEBSTR( OLESTR(" TYPE=\""))
|
|
switch (var.vt & ~VT_ARRAY)
|
|
{
|
|
case VT_I4:
|
|
WRITEBSTR( OLESTR("sint32"))
|
|
break;
|
|
|
|
case VT_R8:
|
|
WRITEBSTR( OLESTR("real64"))
|
|
break;
|
|
|
|
case VT_BOOL:
|
|
WRITEBSTR( OLESTR("boolean"))
|
|
break;
|
|
|
|
case VT_BSTR:
|
|
WRITEBSTR( OLESTR("string"))
|
|
break;
|
|
}
|
|
|
|
WRITEBSTR( OLESTR("\""))
|
|
|
|
// Whether the qualifier is overridable - default is TRUE
|
|
if (WBEM_FLAVOR_NOT_OVERRIDABLE == (WBEM_FLAVOR_MASK_PERMISSIONS & flavor))
|
|
WRITEBSTR( OLESTR(" OVERRIDABLE=\"false\""))
|
|
|
|
// Whether the qualifier is propagated to subclasses - default is TRUE
|
|
if (!(WBEM_FLAVOR_FLAG_PROPAGATE_TO_DERIVED_CLASS & flavor))
|
|
WRITEBSTR( OLESTR(" TOSUBCLASS=\"false\""))
|
|
|
|
// Whether the qualifier is propagated to instances - default is FALSE
|
|
if ((WBEM_FLAVOR_FLAG_PROPAGATE_TO_INSTANCE & flavor))
|
|
WRITEBSTR( OLESTR(" TOINSTANCE=\"true\""))
|
|
|
|
|
|
/* RAJESHR - This change has been put off until the CIM DTD gets modified
|
|
* Whether the qualifier is propagated to instances - default is FALSE
|
|
* This is absent from the CIM DTD
|
|
if (m_bAllowWMIExtensions && (WBEM_FLAVOR_FLAG_PROPAGATE_TO_INSTANCE & flavor))
|
|
WRITEBSTR( OLESTR(" TOINSTANCE=\"true\""))
|
|
*/
|
|
|
|
// Whether the qualifier is an amended one - default is FALSE
|
|
// This is absent from the CIM DTD
|
|
if (m_bAllowWMIExtensions && (WBEM_FLAVOR_AMENDED & flavor))
|
|
WRITEBSTR( OLESTR(" AMENDED=\"true\""))
|
|
|
|
// Currently set TRANSLATABLE as "FALSE" by default. WMI does not use this flavor
|
|
|
|
WRITEBSTR( OLESTR(">"))
|
|
WRITENEWLINE
|
|
|
|
// Now map the value
|
|
MapValue (pOutputStream, var);
|
|
|
|
WRITEBSTR( OLESTR("</QUALIFIER>"))
|
|
|
|
return WBEM_S_NO_ERROR;
|
|
}
|
|
|
|
STDMETHODIMP CWmiToXml::MapValue (IStream *pOutputStream, VARIANT &var)
|
|
{
|
|
if (VT_NULL == var.vt)
|
|
return WBEM_S_NO_ERROR;
|
|
|
|
if (var.vt & VT_ARRAY)
|
|
{
|
|
long uBound = 0;
|
|
if (FAILED(SafeArrayGetUBound (var.parray, 1, &uBound)))
|
|
return WBEM_E_FAILED;
|
|
|
|
WRITEBSTR( OLESTR("<VALUE.ARRAY>"))
|
|
|
|
for (long i = 0; i <= uBound; i++)
|
|
{
|
|
WRITEBSTR( OLESTR("<VALUE>"))
|
|
|
|
// Write the value itself
|
|
switch (var.vt & ~VT_ARRAY)
|
|
{
|
|
case VT_I4:
|
|
{
|
|
long val = 0;
|
|
SafeArrayGetElement (var.parray, &i, &val);
|
|
MapLongValue (pOutputStream, val);
|
|
}
|
|
break;
|
|
|
|
case VT_R8:
|
|
{
|
|
double val = 0;
|
|
SafeArrayGetElement (var.parray, &i, &val);
|
|
MapDoubleValue (pOutputStream, val);
|
|
}
|
|
break;
|
|
|
|
case VT_BOOL:
|
|
{
|
|
VARIANT_BOOL val = 0;
|
|
SafeArrayGetElement (var.parray, &i, &val);
|
|
MapBoolValue (pOutputStream, (val) ? TRUE : FALSE);
|
|
}
|
|
break;
|
|
|
|
case VT_BSTR:
|
|
{
|
|
BSTR val = NULL;
|
|
SafeArrayGetElement (var.parray, &i, &val);
|
|
MapStringValue (pOutputStream, val);
|
|
SysFreeString (val);
|
|
}
|
|
break;
|
|
}
|
|
WRITEBSTR( OLESTR("</VALUE>"))
|
|
WRITENEWLINE
|
|
}
|
|
|
|
WRITEBSTR( OLESTR("</VALUE.ARRAY>"))
|
|
}
|
|
else
|
|
{
|
|
// Simple value
|
|
WRITEBSTR( OLESTR("<VALUE>"))
|
|
switch (var.vt)
|
|
{
|
|
case VT_I4:
|
|
MapLongValue (pOutputStream, var.lVal);
|
|
break;
|
|
|
|
case VT_R8:
|
|
MapDoubleValue (pOutputStream, var.dblVal);
|
|
break;
|
|
|
|
case VT_BOOL:
|
|
MapBoolValue (pOutputStream, (var.boolVal) ? TRUE : FALSE);
|
|
break;
|
|
|
|
case VT_BSTR:
|
|
MapStringValue (pOutputStream, var.bstrVal);
|
|
break;
|
|
}
|
|
|
|
WRITEBSTR( OLESTR("</VALUE>"))
|
|
}
|
|
|
|
return WBEM_S_NO_ERROR;
|
|
}
|
|
|
|
// This function is used to create a KEYVALUE element
|
|
// This element, besides having the value of the property
|
|
// also has a type indicator in the form of the VALUETYPE attribute
|
|
STDMETHODIMP CWmiToXml::MapKeyValue (IStream *pOutputStream, VARIANT &var)
|
|
{
|
|
ParsedObjectPath *pObjectPath = NULL;
|
|
|
|
// This could be simple value or a reference value
|
|
// Note that keys are not allowed to be arrays
|
|
if (IsReference (var, &pObjectPath))
|
|
{
|
|
// If the above function returns true, then we're sure that the variant is of type VT_BSTR
|
|
MapReferenceValue (pOutputStream, pObjectPath, var.bstrVal);
|
|
delete pObjectPath;
|
|
}
|
|
else
|
|
{
|
|
// Simple value
|
|
WRITEBSTR( OLESTR("<KEYVALUE"))
|
|
|
|
switch (var.vt)
|
|
{
|
|
case VT_I4:
|
|
WRITEBSTR( OLESTR(" VALUETYPE=\"numeric\">"))
|
|
MapLongValue (pOutputStream, var.lVal);
|
|
break;
|
|
|
|
case VT_R8:
|
|
WRITEBSTR( OLESTR(" VALUETYPE=\"numeric\">"))
|
|
MapDoubleValue (pOutputStream, var.dblVal);
|
|
break;
|
|
|
|
case VT_BOOL:
|
|
WRITEBSTR( OLESTR(" VALUETYPE=\"boolean\">"))
|
|
MapBoolValue (pOutputStream, (var.boolVal) ? TRUE : FALSE);
|
|
break;
|
|
|
|
case VT_BSTR:
|
|
WRITEBSTR(OLESTR(" VALUETYPE=\"string\">"))
|
|
// RAJESHR - We assume that the object path parser will have suitably unescaped
|
|
// the escaped characters in the object path
|
|
// If this is not the case, then we need to unescape it manually
|
|
MapStringValue (pOutputStream, var.bstrVal);
|
|
break;
|
|
}
|
|
|
|
WRITEBSTR( OLESTR("</KEYVALUE>"))
|
|
}
|
|
|
|
return WBEM_S_NO_ERROR;
|
|
}
|
|
|
|
// In this function we produce PROPERTY elements for each of the properties of an IWbemClassObject
|
|
// or if a property list is specified, then only for each of the properties in that list
|
|
STDMETHODIMP CWmiToXml::MapProperties (IStream *pOutputStream, IWbemClassObject *pObject, BSTR *ppPropertyList, DWORD dwNumProperties, BSTR strClassBasis, bool bIsClass)
|
|
{
|
|
// Check to see if a property list is specified. If so, we map only those properties
|
|
if (dwNumProperties && ppPropertyList)
|
|
{
|
|
VARIANT var;
|
|
VariantInit (&var);
|
|
long flavor = 0;
|
|
CIMTYPE cimtype = CIM_ILLEGAL;
|
|
|
|
for (DWORD i = 0; i < dwNumProperties; i++)
|
|
{
|
|
// A class basis may be optionally specified for this class
|
|
// this happens in case of Enumerations and we have to filter out derived class properties
|
|
// since the DMTF concept of SHALLOW enumeration is differnet from WMI's definition
|
|
if (PropertyDefinedForClass (pObject, ppPropertyList [i], strClassBasis))
|
|
{
|
|
if (WBEM_S_NO_ERROR == pObject->Get (ppPropertyList [i], 0, &var, &cimtype, &flavor))
|
|
{
|
|
switch (cimtype & ~CIM_FLAG_ARRAY)
|
|
{
|
|
case CIM_OBJECT:
|
|
MapObjectProperty (pOutputStream, pObject, ppPropertyList [i], var, (cimtype & CIM_FLAG_ARRAY) ? TRUE : FALSE, flavor, bIsClass);
|
|
break;
|
|
|
|
case CIM_REFERENCE:
|
|
MapReferenceProperty (pOutputStream, pObject, ppPropertyList [i], var, (cimtype & CIM_FLAG_ARRAY) ? TRUE : FALSE, flavor,bIsClass);
|
|
break;
|
|
|
|
default:
|
|
MapProperty (pOutputStream, pObject, ppPropertyList [i], var, cimtype & ~CIM_FLAG_ARRAY,
|
|
(cimtype & CIM_FLAG_ARRAY) ? TRUE : FALSE, flavor, bIsClass);
|
|
break;
|
|
}
|
|
VariantClear (&var);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Note that we cannot set the LOCAL_ONLY flag for the enumeration since this is mutually exclusive
|
|
// with the NONSYSTEM Flag.
|
|
// Hence we use the property flavour to check whether it is local or not below.
|
|
// We dont want System propertied going to DMTF servers
|
|
if(SUCCEEDED(pObject->BeginEnumeration (
|
|
(m_bAllowWMIExtensions == VARIANT_FALSE || m_bExcludeSystemProperties == VARIANT_TRUE)? WBEM_FLAG_NONSYSTEM_ONLY : 0)))
|
|
{
|
|
VARIANT var;
|
|
VariantInit (&var);
|
|
long flavor = 0;
|
|
CIMTYPE cimtype = CIM_ILLEGAL;
|
|
BSTR name = NULL;
|
|
|
|
while (WBEM_S_NO_ERROR == pObject->Next (0, &name, &var, &cimtype, &flavor))
|
|
{
|
|
// If only local properties are being asked for, then skip this if it is not local
|
|
// Dont skip system properties though
|
|
if(m_bLocalOnly == VARIANT_FALSE ||
|
|
(m_bLocalOnly == VARIANT_TRUE &&
|
|
((flavor == WBEM_FLAVOR_ORIGIN_LOCAL) || (flavor == WBEM_FLAVOR_ORIGIN_SYSTEM)) ))
|
|
{
|
|
// A class basis may be optionally specified for this call
|
|
// this happens in case of Enumerations and we have to filter out derived class properties
|
|
// since the DMTF concept of SHALLOW enumeration is differnet from WMI's definition
|
|
if (PropertyDefinedForClass (pObject, name,strClassBasis))
|
|
{
|
|
switch (cimtype & ~CIM_FLAG_ARRAY)
|
|
{
|
|
case CIM_OBJECT:
|
|
MapObjectProperty (pOutputStream, pObject, name, var, (cimtype & CIM_FLAG_ARRAY) ? TRUE : FALSE, flavor, bIsClass);
|
|
break;
|
|
|
|
case CIM_REFERENCE:
|
|
MapReferenceProperty (pOutputStream, pObject, name, var, (cimtype & CIM_FLAG_ARRAY) ? TRUE : FALSE, flavor, bIsClass);
|
|
break;
|
|
|
|
default:
|
|
MapProperty (pOutputStream, pObject, name, var, cimtype & ~CIM_FLAG_ARRAY,
|
|
(cimtype & CIM_FLAG_ARRAY) ? TRUE : FALSE, flavor, bIsClass);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
SysFreeString (name);
|
|
VariantClear (&var);
|
|
}
|
|
}
|
|
|
|
pObject->EndEnumeration ();
|
|
}
|
|
return WBEM_S_NO_ERROR;
|
|
}
|
|
|
|
STDMETHODIMP CWmiToXml::MapProperty (IStream *pOutputStream, IWbemClassObject *pObject, BSTR name, VARIANT &var, CIMTYPE cimtype,
|
|
BOOL isArray, long flavor, bool bIsClass)
|
|
{
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
|
|
// The property name
|
|
if (isArray)
|
|
WRITEBSTR( OLESTR("<PROPERTY.ARRAY NAME=\""))
|
|
else
|
|
WRITEBSTR( OLESTR("<PROPERTY NAME=\""))
|
|
WRITEBSTR( name)
|
|
WRITEBSTR( OLESTR("\""));
|
|
|
|
// The originating class of this property
|
|
BSTR propertyOrigin = NULL;
|
|
|
|
if (WBEM_S_NO_ERROR == pObject->GetPropertyOrigin (name, &propertyOrigin))
|
|
{
|
|
MapClassOrigin (pOutputStream, propertyOrigin, bIsClass);
|
|
SysFreeString(propertyOrigin);
|
|
}
|
|
|
|
MapLocal (pOutputStream, flavor);
|
|
|
|
// The property CIM type
|
|
hr = MapType (pOutputStream, cimtype);
|
|
|
|
// Get the Qualifier Set of the property at this time
|
|
// Note that system properties do not have qualifiers sets
|
|
// Map the Array Size attribute if this is an array type
|
|
IWbemQualifierSet *pQualSet= NULL;
|
|
if (SUCCEEDED(hr) && (_wcsnicmp(name, L"__", 2) != 0) )
|
|
{
|
|
if(WBEM_S_NO_ERROR == (hr = pObject->GetPropertyQualifierSet (name, &pQualSet)))
|
|
{
|
|
if (isArray)
|
|
MapArraySize (pOutputStream, pQualSet);
|
|
}
|
|
}
|
|
|
|
WRITEBSTR( OLESTR(">"))
|
|
WRITENEWLINE
|
|
|
|
// Map the qualifiers (note that system properties have no qualifiers)
|
|
if(SUCCEEDED(hr) && pQualSet)
|
|
hr = MapQualifiers (pOutputStream, pQualSet);
|
|
|
|
// Now map the value
|
|
if(SUCCEEDED(hr))
|
|
hr = MapValue (pOutputStream, cimtype, isArray, var);
|
|
|
|
if (isArray)
|
|
WRITEBSTR( OLESTR("</PROPERTY.ARRAY>"))
|
|
else
|
|
WRITEBSTR( OLESTR("</PROPERTY>"))
|
|
|
|
if(pQualSet)
|
|
pQualSet->Release ();
|
|
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CWmiToXml::MapObjectProperty (IStream *pOutputStream, IWbemClassObject *pObject, BSTR name, VARIANT &var,
|
|
BOOL isArray, long flavor, bool bIsClass)
|
|
{
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
IWbemQualifierSet *pQualSet= NULL;
|
|
|
|
/*
|
|
* Only map embedded objects when WMI extensions are allowed
|
|
*/
|
|
|
|
if (m_bAllowWMIExtensions)
|
|
{
|
|
if (WBEM_S_NO_ERROR == (hr = pObject->GetPropertyQualifierSet (name, &pQualSet)))
|
|
{
|
|
// The property name
|
|
if (isArray)
|
|
WRITEBSTR( OLESTR("<PROPERTY.OBJECTARRAY NAME=\""))
|
|
else
|
|
WRITEBSTR( OLESTR("<PROPERTY.OBJECT NAME=\""))
|
|
WRITEBSTR( name)
|
|
WRITEBSTR( OLESTR("\""));
|
|
|
|
// The originating class of this property
|
|
BSTR propertyOrigin = NULL;
|
|
|
|
if (WBEM_S_NO_ERROR == pObject->GetPropertyOrigin (name, &propertyOrigin))
|
|
{
|
|
MapClassOrigin (pOutputStream, propertyOrigin, bIsClass);
|
|
SysFreeString(propertyOrigin);
|
|
}
|
|
|
|
MapLocal (pOutputStream, flavor);
|
|
MapStrongType (pOutputStream, pQualSet);
|
|
|
|
if (isArray)
|
|
MapArraySize (pOutputStream, pQualSet);
|
|
|
|
WRITEBSTR( OLESTR(">"))
|
|
WRITENEWLINE
|
|
|
|
MapQualifiers (pOutputStream, pQualSet);
|
|
|
|
// Now map the value
|
|
hr = MapEmbeddedObjectValue (pOutputStream, isArray, var);
|
|
|
|
if (isArray)
|
|
WRITEBSTR( OLESTR("</PROPERTY.OBJECTARRAY>"))
|
|
else
|
|
WRITEBSTR( OLESTR("</PROPERTY.OBJECT>"))
|
|
|
|
pQualSet->Release ();
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
void CWmiToXml::MapArraySize (IStream *pOutputStream, IWbemQualifierSet *pQualSet)
|
|
{
|
|
// RAJESHR - RAID 29167 covers the fact that case (1) below
|
|
// should not be valid (but this is what the MOF compiler
|
|
// does) - need to change the code when that bug is fixed
|
|
// to be more strict.
|
|
|
|
/*
|
|
* We defined the ARRAYSIZE element if the qualifier set
|
|
* satisfies one of the following constraints:
|
|
*
|
|
* 1) MAX is present with a positive integer value, and MIN
|
|
* is absent.
|
|
*
|
|
* 2) MAX and MIN are both present, with the same positive
|
|
* integer value.
|
|
*/
|
|
|
|
VARIANT var;
|
|
VariantInit (&var);
|
|
BOOL isFixed = FALSE;
|
|
|
|
if (WBEM_S_NO_ERROR == pQualSet->Get(L"MAX", 0, &var, NULL))
|
|
{
|
|
if ((V_VT(&var) == VT_I4) && (0 < var.lVal))
|
|
{
|
|
// Promising - have a candidate MAX value. Now
|
|
// look for a MIN
|
|
long arraySize = var.lVal;
|
|
|
|
if (WBEM_S_NO_ERROR == pQualSet->Get(L"MIN", 0, &var, NULL))
|
|
{
|
|
if ((V_VT(&var) == VT_I4) && (0 < var.lVal))
|
|
{
|
|
// Have a value - check if it's the same as MAX
|
|
|
|
isFixed = (arraySize == var.lVal);
|
|
}
|
|
}
|
|
else
|
|
isFixed = TRUE; // NO MIN only max
|
|
}
|
|
}
|
|
|
|
if (isFixed)
|
|
{
|
|
WRITEBSTR( OLESTR(" ARRAYSIZE=\""))
|
|
MapLongValue (pOutputStream, var.lVal);
|
|
WRITEBSTR( OLESTR("\""))
|
|
}
|
|
|
|
VariantClear (&var);
|
|
}
|
|
|
|
void CWmiToXml::MapStrongType (IStream *pOutputStream, IWbemQualifierSet *pQualSet)
|
|
{
|
|
VARIANT var;
|
|
VariantInit(&var);
|
|
|
|
if ((WBEM_S_NO_ERROR == pQualSet->Get(L"CIMTYPE", 0, &var, NULL))
|
|
&& (VT_BSTR == var.vt))
|
|
{
|
|
// Split out the class (if any) from the ref
|
|
LPWSTR ptr = wcschr (var.bstrVal, OLECHAR(':'));
|
|
|
|
if ((NULL != ptr) && (1 < wcslen(ptr)))
|
|
{
|
|
int classLen = wcslen(ptr) - 1;
|
|
LPWSTR classPtr = NULL;
|
|
if(classPtr = new OLECHAR[classLen + 1])
|
|
{
|
|
wcscpy (classPtr, ptr+1);
|
|
BSTR pszClass = NULL;
|
|
if(pszClass = SysAllocString(classPtr))
|
|
{
|
|
WRITEBSTR( OLESTR(" REFERENCECLASS=\""))
|
|
WRITEBSTR( pszClass)
|
|
WRITEBSTR( OLESTR("\""))
|
|
SysFreeString(pszClass);
|
|
}
|
|
delete [] classPtr;
|
|
}
|
|
}
|
|
}
|
|
|
|
VariantClear(&var);
|
|
}
|
|
|
|
STDMETHODIMP CWmiToXml::MapType (IStream *pOutputStream, CIMTYPE cimtype)
|
|
{
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
|
|
WRITEBSTR( OLESTR(" TYPE=\""))
|
|
switch (cimtype)
|
|
{
|
|
case CIM_SINT8:
|
|
WRITEBSTR( OLESTR("sint8"))
|
|
break;
|
|
|
|
case CIM_UINT8:
|
|
WRITEBSTR( OLESTR("uint8"))
|
|
break;
|
|
|
|
case CIM_SINT16:
|
|
WRITEBSTR( OLESTR("sint16"))
|
|
break;
|
|
|
|
case CIM_UINT16:
|
|
WRITEBSTR( OLESTR("uint16"))
|
|
break;
|
|
|
|
case CIM_SINT32:
|
|
WRITEBSTR( OLESTR("sint32"))
|
|
break;
|
|
|
|
case CIM_UINT32:
|
|
WRITEBSTR( OLESTR("uint32"))
|
|
break;
|
|
|
|
case CIM_SINT64:
|
|
WRITEBSTR( OLESTR("sint64"))
|
|
break;
|
|
|
|
case CIM_UINT64:
|
|
WRITEBSTR( OLESTR("uint64"))
|
|
break;
|
|
|
|
case CIM_REAL32:
|
|
WRITEBSTR( OLESTR("real32"))
|
|
break;
|
|
|
|
case CIM_REAL64:
|
|
WRITEBSTR( OLESTR("real64"))
|
|
break;
|
|
|
|
case CIM_BOOLEAN:
|
|
WRITEBSTR( OLESTR("boolean"))
|
|
break;
|
|
|
|
case CIM_STRING:
|
|
WRITEBSTR( OLESTR("string"))
|
|
break;
|
|
|
|
case CIM_DATETIME:
|
|
WRITEBSTR( OLESTR("datetime"))
|
|
break;
|
|
|
|
case CIM_CHAR16:
|
|
WRITEBSTR( OLESTR("char16"))
|
|
break;
|
|
|
|
default:
|
|
// Don't recognize this type
|
|
hr = WBEM_E_FAILED;
|
|
}
|
|
|
|
WRITEBSTR( OLESTR("\""))
|
|
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CWmiToXml::MapValue (IStream *pOutputStream, CIMTYPE cimtype, BOOL isArray, VARIANT &var)
|
|
{
|
|
if (VT_NULL == var.vt)
|
|
return WBEM_S_NO_ERROR;
|
|
|
|
if (isArray)
|
|
{
|
|
long uBound = 0;
|
|
if (FAILED(SafeArrayGetUBound (var.parray, 1, &uBound)))
|
|
return WBEM_E_FAILED;
|
|
|
|
WRITEBSTR( OLESTR("<VALUE.ARRAY>"))
|
|
|
|
for (long i = 0; i <= uBound; i++)
|
|
{
|
|
WRITEBSTR( OLESTR("<VALUE>"))
|
|
|
|
switch (cimtype)
|
|
{
|
|
case CIM_UINT8:
|
|
{
|
|
unsigned char val = 0;
|
|
SafeArrayGetElement (var.parray, &i, &val);
|
|
MapByteValue (pOutputStream, val);
|
|
}
|
|
break;
|
|
|
|
case CIM_SINT8:
|
|
case CIM_SINT16:
|
|
{
|
|
short val = 0;
|
|
SafeArrayGetElement (var.parray, &i, &val);
|
|
MapShortValue (pOutputStream, val);
|
|
}
|
|
break;
|
|
|
|
case CIM_UINT16:
|
|
case CIM_UINT32:
|
|
case CIM_SINT32:
|
|
{
|
|
long val = 0;
|
|
SafeArrayGetElement (var.parray, &i, &val);
|
|
MapLongValue (pOutputStream, val);
|
|
}
|
|
break;
|
|
|
|
case CIM_REAL32:
|
|
{
|
|
float val = 0;
|
|
SafeArrayGetElement (var.parray, &i, &val);
|
|
MapFloatValue (pOutputStream, val);
|
|
}
|
|
break;
|
|
|
|
case CIM_REAL64:
|
|
{
|
|
double val = 0;
|
|
SafeArrayGetElement (var.parray, &i, &val);
|
|
MapDoubleValue (pOutputStream, val);
|
|
}
|
|
break;
|
|
|
|
case CIM_BOOLEAN:
|
|
{
|
|
VARIANT_BOOL val = 0;
|
|
SafeArrayGetElement (var.parray, &i, &val);
|
|
MapBoolValue (pOutputStream, (val)? TRUE : FALSE);
|
|
}
|
|
break;
|
|
|
|
case CIM_CHAR16:
|
|
{
|
|
long val = 0;
|
|
SafeArrayGetElement (var.parray, &i, &val);
|
|
MapCharValue (pOutputStream, val);
|
|
}
|
|
break;
|
|
|
|
case CIM_STRING:
|
|
{
|
|
BSTR val = NULL;
|
|
SafeArrayGetElement (var.parray, &i, &val);
|
|
MapStringValue (pOutputStream, val);
|
|
SysFreeString (val);
|
|
}
|
|
break;
|
|
|
|
case CIM_UINT64:
|
|
case CIM_SINT64:
|
|
case CIM_DATETIME:
|
|
{
|
|
BSTR val = NULL;
|
|
SafeArrayGetElement (var.parray, &i, &val);
|
|
WRITEBSTR( val)
|
|
SysFreeString(val);
|
|
}
|
|
break;
|
|
}
|
|
WRITEBSTR( OLESTR("</VALUE>"))
|
|
WRITENEWLINE
|
|
}
|
|
|
|
WRITEBSTR( OLESTR("</VALUE.ARRAY>"))
|
|
}
|
|
else
|
|
{
|
|
// Simple value
|
|
WRITEBSTR( OLESTR("<VALUE>"))
|
|
switch (cimtype)
|
|
{
|
|
case CIM_UINT8:
|
|
MapByteValue (pOutputStream, var.bVal);
|
|
break;
|
|
|
|
case CIM_SINT8:
|
|
case CIM_SINT16:
|
|
MapShortValue (pOutputStream, var.iVal);
|
|
break;
|
|
|
|
case CIM_UINT16:
|
|
case CIM_UINT32:
|
|
case CIM_SINT32:
|
|
MapLongValue (pOutputStream, var.lVal);
|
|
break;
|
|
|
|
case CIM_REAL32:
|
|
MapFloatValue (pOutputStream, var.fltVal);
|
|
break;
|
|
|
|
case CIM_REAL64:
|
|
MapDoubleValue (pOutputStream, var.dblVal);
|
|
break;
|
|
|
|
case CIM_BOOLEAN:
|
|
MapBoolValue (pOutputStream, (var.boolVal) ? TRUE : FALSE);
|
|
break;
|
|
|
|
case CIM_CHAR16:
|
|
MapCharValue (pOutputStream, var.lVal);
|
|
break;
|
|
|
|
case CIM_STRING:
|
|
MapStringValue (pOutputStream, var.bstrVal);
|
|
break;
|
|
|
|
case CIM_UINT64:
|
|
case CIM_SINT64:
|
|
case CIM_DATETIME:
|
|
WRITEBSTR( var.bstrVal)
|
|
break;
|
|
}
|
|
WRITEBSTR( OLESTR("</VALUE>"))
|
|
}
|
|
|
|
return WBEM_S_NO_ERROR;
|
|
}
|
|
|
|
STDMETHODIMP CWmiToXml::MapEmbeddedObjectValue (IStream *pOutputStream, BOOL isArray, VARIANT &var)
|
|
{
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
|
|
if (VT_NULL == var.vt)
|
|
return WBEM_S_NO_ERROR;
|
|
|
|
if (isArray)
|
|
{
|
|
long uBound = 0;
|
|
if (FAILED(SafeArrayGetUBound (var.parray, 1, &uBound)))
|
|
return WBEM_E_FAILED;
|
|
|
|
WRITEBSTR(OLESTR("<VALUE.OBJECTARRAY>"))
|
|
for (long i = 0; i<=uBound; i++)
|
|
{
|
|
IUnknown *pNextElement = NULL;
|
|
if(SUCCEEDED(hr = SafeArrayGetElement(var.parray, (LONG *)&i, (LPVOID )&pNextElement )))
|
|
{
|
|
IWbemClassObject *pEmbeddedObject = NULL;
|
|
if(SUCCEEDED(hr = pNextElement->QueryInterface(IID_IWbemClassObject, (LPVOID *)&pEmbeddedObject)))
|
|
{
|
|
// Note that we always use PathLevelAnonymous here since embedded objects are VALUE.OBJECTs as per the DTD
|
|
CWmiToXml wbemToXml;
|
|
wbemToXml.m_iPathLevel = pathLevelAnonymous;
|
|
wbemToXml.m_bAllowWMIExtensions = m_bAllowWMIExtensions;
|
|
wbemToXml.m_iQualifierFilter = m_iQualifierFilter;
|
|
wbemToXml.m_iClassOriginFilter = m_iClassOriginFilter;
|
|
WRITEBSTR(OLESTR("<VALUE.OBJECT>"))
|
|
hr = wbemToXml.MapObjectToXML(pEmbeddedObject, NULL, 0, NULL, pOutputStream, NULL);
|
|
WRITEBSTR(OLESTR("</VALUE.OBJECT>"))
|
|
pEmbeddedObject->Release();
|
|
}
|
|
pNextElement->Release();
|
|
pNextElement = NULL;
|
|
}
|
|
}
|
|
WRITEBSTR(OLESTR("</VALUE.OBJECTARRAY>"))
|
|
}
|
|
else
|
|
{
|
|
// Note that we always use PathLevelAnonymous here since embedded objects are VALUE.OBJECTs as per the DTD
|
|
IWbemClassObject *pEmbeddedObject = NULL;
|
|
if(SUCCEEDED(hr = (var.punkVal)->QueryInterface(IID_IWbemClassObject, (LPVOID *)&pEmbeddedObject)))
|
|
{
|
|
|
|
WRITEBSTR(OLESTR("<VALUE.OBJECT>"))
|
|
CWmiToXml wbemToXml;
|
|
wbemToXml.m_iPathLevel = pathLevelAnonymous;
|
|
wbemToXml.m_bAllowWMIExtensions = m_bAllowWMIExtensions;
|
|
wbemToXml.m_iQualifierFilter = m_iQualifierFilter;
|
|
wbemToXml.m_iClassOriginFilter = m_iClassOriginFilter;
|
|
hr = wbemToXml.MapObjectToXML(pEmbeddedObject, NULL, 0, NULL, pOutputStream, NULL);
|
|
pEmbeddedObject->Release();
|
|
WRITEBSTR(OLESTR("</VALUE.OBJECT>"))
|
|
}
|
|
}
|
|
return WBEM_S_NO_ERROR;
|
|
}
|
|
|
|
STDMETHODIMP CWmiToXml::MapMethods (IStream *pOutputStream, IWbemClassObject *pObject)
|
|
{
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
|
|
// Map the requested filter (local only) to the flags value - default is ALL
|
|
LONG lFlags = 0;
|
|
if (VARIANT_TRUE == m_bLocalOnly)
|
|
lFlags = WBEM_FLAG_LOCAL_ONLY;
|
|
|
|
pObject->BeginMethodEnumeration (lFlags);
|
|
BSTR name = NULL;
|
|
IWbemClassObject *pInParams = NULL;
|
|
IWbemClassObject *pOutParams = NULL;
|
|
|
|
while (WBEM_S_NO_ERROR == pObject->NextMethod (0, &name, &pInParams, &pOutParams))
|
|
{
|
|
MapMethod (pOutputStream, pObject, name, pInParams, pOutParams);
|
|
|
|
if (pInParams)
|
|
{
|
|
pInParams->Release ();
|
|
pInParams = NULL;
|
|
}
|
|
|
|
if (pOutParams)
|
|
{
|
|
pOutParams->Release ();
|
|
pOutParams = NULL;
|
|
}
|
|
|
|
SysFreeString (name);
|
|
}
|
|
|
|
pObject->EndMethodEnumeration ();
|
|
return WBEM_S_NO_ERROR;
|
|
}
|
|
|
|
void CWmiToXml::MapMethod (IStream *pOutputStream, IWbemClassObject *pObject, BSTR name, IWbemClassObject *pInParams, IWbemClassObject *pOutParams)
|
|
{
|
|
HRESULT result = E_FAIL;
|
|
CIMTYPE returnCimtype = 0;
|
|
VARIANT vVariant;
|
|
VariantInit(&vVariant);
|
|
|
|
// First we need the return type of the method, if any
|
|
if (pOutParams)
|
|
{
|
|
if (SUCCEEDED(result = pOutParams->Get (L"ReturnValue", 0, &vVariant, &returnCimtype, NULL)))
|
|
{
|
|
switch(returnCimtype)
|
|
{
|
|
case CIM_OBJECT:
|
|
if(m_bAllowWMIExtensions)
|
|
WRITEBSTR(OLESTR("<METHOD.OBJECT NAME=\""))
|
|
else
|
|
{
|
|
// Just skip this method if WMI extensions are not allowed
|
|
VariantClear(&vVariant);
|
|
return;
|
|
}
|
|
break;
|
|
case CIM_REFERENCE:
|
|
if(m_bAllowWMIExtensions)
|
|
WRITEBSTR(OLESTR("<METHOD.REFERENCE NAME=\""))
|
|
else
|
|
{
|
|
// Just skip this method if WMI extensions are not allowed
|
|
VariantClear(&vVariant);
|
|
return;
|
|
}
|
|
break;
|
|
default:
|
|
WRITEBSTR(OLESTR("<METHOD NAME=\""))
|
|
break;
|
|
}
|
|
}
|
|
else if (result == WBEM_E_NOT_FOUND) // So this method returns a void
|
|
{
|
|
WRITEBSTR(OLESTR("<METHOD NAME=\""))
|
|
}
|
|
}
|
|
else // This method returns a VOID
|
|
{
|
|
WRITEBSTR(OLESTR("<METHOD NAME=\""))
|
|
}
|
|
|
|
|
|
// The method name
|
|
WRITEBSTR(name)
|
|
WRITEBSTR(OLESTR("\" "))
|
|
|
|
// The method return type (default is void). This is the type of
|
|
// the ReturnType property if present (otherwise defaults to void)
|
|
MapMethodReturnType(pOutputStream, &vVariant, returnCimtype, pOutParams);
|
|
VariantClear(&vVariant);
|
|
|
|
// The class origin
|
|
BSTR methodOrigin = NULL;
|
|
|
|
if (WBEM_S_NO_ERROR == pObject->GetMethodOrigin (name, &methodOrigin))
|
|
{
|
|
MapClassOrigin (pOutputStream, methodOrigin, true);
|
|
SysFreeString(methodOrigin);
|
|
}
|
|
|
|
WRITEBSTR( OLESTR(">"))
|
|
WRITENEWLINE
|
|
|
|
// Now do the qualifiers of the method
|
|
IWbemQualifierSet *pQualSet = NULL;
|
|
if (WBEM_S_NO_ERROR == pObject->GetMethodQualifierSet (name, &pQualSet))
|
|
{
|
|
MapQualifiers (pOutputStream, pQualSet);
|
|
pQualSet->Release ();
|
|
pQualSet = NULL;
|
|
}
|
|
|
|
VARIANT idVar;
|
|
VariantInit (&idVar);
|
|
idVar.vt = VT_I4;
|
|
idVar.lVal = 0;
|
|
|
|
long nextId = 0; // The next method ID to expect
|
|
long fixedIndex = 0;
|
|
|
|
// For each id,
|
|
// Get the name of the parameter (could be in, out or both)
|
|
// If just an in-parameter or just an out-parameter it's easy
|
|
// If both it's a bit tricky
|
|
//=========================================================================
|
|
|
|
while (TRUE)
|
|
{
|
|
BSTR nextInParamName = NULL;
|
|
BSTR nextOutParamName = NULL;
|
|
|
|
if (pInParams)
|
|
{
|
|
SAFEARRAY *pArray = NULL;
|
|
|
|
if (WBEM_S_NO_ERROR ==
|
|
pInParams->GetNames (L"ID", WBEM_FLAG_ONLY_IF_IDENTICAL|WBEM_FLAG_NONSYSTEM_ONLY,
|
|
&idVar, &pArray))
|
|
{
|
|
// Did we get a match?
|
|
if (pArray)
|
|
{
|
|
if ((1 == pArray->cDims) && (1 == (pArray->rgsabound[0]).cElements))
|
|
SafeArrayGetElement (pArray, &fixedIndex, &nextInParamName);
|
|
|
|
SafeArrayDestroy (pArray);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (pOutParams)
|
|
{
|
|
SAFEARRAY *pArray = NULL;
|
|
|
|
if (WBEM_S_NO_ERROR ==
|
|
pOutParams->GetNames (L"ID", WBEM_FLAG_ONLY_IF_IDENTICAL|WBEM_FLAG_NONSYSTEM_ONLY,
|
|
&idVar, &pArray))
|
|
{
|
|
// Did we get a match?
|
|
if (pArray)
|
|
{
|
|
if ((1 == pArray->cDims) && (1 == (pArray->rgsabound[0]).cElements))
|
|
SafeArrayGetElement (pArray, &fixedIndex, &nextOutParamName);
|
|
|
|
SafeArrayDestroy (pArray);
|
|
}
|
|
}
|
|
}
|
|
|
|
// If [in] or [out] this is easy
|
|
if ((nextInParamName && !nextOutParamName) || (!nextInParamName && nextOutParamName))
|
|
{
|
|
VARIANT var;
|
|
VariantInit (&var);
|
|
IWbemQualifierSet *pParamQualSet = NULL;
|
|
CIMTYPE cimtype = 0;
|
|
|
|
if (nextInParamName)
|
|
{
|
|
if (WBEM_S_NO_ERROR == pInParams->Get (nextInParamName, 0, &var, &cimtype, NULL))
|
|
{
|
|
pInParams->GetPropertyQualifierSet (nextInParamName, &pParamQualSet);
|
|
MapParameter(pOutputStream, nextInParamName, pParamQualSet, cimtype);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (WBEM_S_NO_ERROR == pOutParams->Get (nextOutParamName, 0, &var, &cimtype, NULL))
|
|
{
|
|
pOutParams->GetPropertyQualifierSet (nextOutParamName, &pParamQualSet);
|
|
MapParameter(pOutputStream, nextOutParamName, pParamQualSet, cimtype);
|
|
}
|
|
}
|
|
|
|
if (pParamQualSet)
|
|
pParamQualSet->Release ();
|
|
|
|
VariantClear (&var);
|
|
}
|
|
else if (nextInParamName && nextOutParamName)
|
|
{
|
|
// The [in,out] case and we have to do a merge
|
|
|
|
if (0 == _wcsicmp (nextInParamName, nextOutParamName))
|
|
{
|
|
VARIANT var;
|
|
VariantInit (&var);
|
|
CIMTYPE cimtype = 0;
|
|
|
|
IWbemQualifierSet *pInParamQualSet = NULL;
|
|
IWbemQualifierSet *pOutParamQualSet = NULL;
|
|
|
|
if (WBEM_S_NO_ERROR == pInParams->Get (nextInParamName, 0, &var, &cimtype, NULL))
|
|
{
|
|
pInParams->GetPropertyQualifierSet (nextInParamName, &pInParamQualSet);
|
|
pOutParams->GetPropertyQualifierSet (nextInParamName, &pOutParamQualSet);
|
|
MapParameter(pOutputStream, nextInParamName, pInParamQualSet, cimtype, pOutParamQualSet);
|
|
|
|
}
|
|
|
|
if (pInParamQualSet)
|
|
pInParamQualSet->Release ();
|
|
|
|
if (pOutParamQualSet)
|
|
pOutParamQualSet->Release ();
|
|
|
|
VariantClear (&var);
|
|
}
|
|
else
|
|
{
|
|
// Bad news - conflicting IDs in the [in] and [out] parameter set
|
|
// This cannot be a valid method definition
|
|
SysFreeString (nextInParamName);
|
|
SysFreeString (nextOutParamName);
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Next id not found - stop now and break out
|
|
SysFreeString (nextInParamName);
|
|
SysFreeString (nextOutParamName);
|
|
break;
|
|
}
|
|
|
|
SysFreeString (nextInParamName);
|
|
SysFreeString (nextOutParamName);
|
|
idVar.iVal = idVar.iVal + 1;
|
|
}
|
|
|
|
switch(returnCimtype)
|
|
{
|
|
case CIM_OBJECT:
|
|
WRITEBSTR(OLESTR("</METHOD.OBJECT>"))
|
|
break;
|
|
case CIM_REFERENCE:
|
|
WRITEBSTR(OLESTR("</METHOD.REFERENCE>"))
|
|
break;
|
|
default:
|
|
WRITEBSTR(OLESTR("</METHOD>"))
|
|
break;
|
|
}
|
|
}
|
|
|
|
STDMETHODIMP CWmiToXml::MapMethodReturnType(IStream *pOutputStream, VARIANT *pValue, CIMTYPE returnCimType, IWbemClassObject *pOutputParams)
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
switch(returnCimType)
|
|
{
|
|
// Write a REFERENCECLASS
|
|
case CIM_OBJECT:
|
|
case CIM_REFERENCE:
|
|
{
|
|
IWbemQualifierSet *pQualifierSet = NULL;
|
|
if(SUCCEEDED(hr = pOutputParams->GetPropertyQualifierSet(L"ReturnValue", &pQualifierSet)))
|
|
{
|
|
// Map the type of the return class
|
|
MapStrongType(pOutputStream, pQualifierSet);
|
|
pQualifierSet->Release();
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
hr = MapType(pOutputStream, returnCimType);
|
|
break;
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
void CWmiToXml::MapClassOrigin (IStream *pOutputStream, BSTR &classOrigin, bool bIsClass)
|
|
{
|
|
if ( (bIsClass && (m_iClassOriginFilter & wmiXMLClassOriginFilterClass)) ||
|
|
(m_iClassOriginFilter & wmiXMLClassOriginFilterInstance) )
|
|
{
|
|
WRITEBSTR( OLESTR(" CLASSORIGIN=\""))
|
|
WRITEBSTR( classOrigin)
|
|
WRITEBSTR( OLESTR("\""))
|
|
}
|
|
}
|
|
|
|
void CWmiToXml::MapParameter (IStream *pOutputStream, BSTR paramName,
|
|
IWbemQualifierSet *pQualSet,
|
|
CIMTYPE cimtype,
|
|
IWbemQualifierSet *pQualSet2)
|
|
{
|
|
/*
|
|
* For vanilla CIM XML we don't handle embedded object parameters
|
|
*/
|
|
|
|
if ((CIM_OBJECT != (cimtype & ~CIM_FLAG_ARRAY)) || m_bAllowWMIExtensions)
|
|
{
|
|
if (cimtype & CIM_FLAG_ARRAY)
|
|
{
|
|
// Map the array parameter
|
|
if (CIM_REFERENCE == (cimtype & ~CIM_FLAG_ARRAY))
|
|
{
|
|
WRITEBSTR( OLESTR("<PARAMETER.REFARRAY NAME=\""))
|
|
WRITEBSTR( paramName)
|
|
WRITEBSTR( OLESTR("\" "))
|
|
MapStrongType (pOutputStream, pQualSet);
|
|
WRITEBSTR( OLESTR(" "))
|
|
MapArraySize (pOutputStream, pQualSet);
|
|
WRITEBSTR( OLESTR(">"))
|
|
WRITENEWLINE
|
|
|
|
// Map the qualifiers of the parameter
|
|
if (pQualSet || pQualSet2)
|
|
MapQualifiers (pOutputStream, pQualSet, pQualSet2);
|
|
|
|
WRITEBSTR( OLESTR("</PARAMETER.REFARRAY>"))
|
|
}
|
|
else if (CIM_OBJECT == (cimtype & ~CIM_FLAG_ARRAY))
|
|
{
|
|
WRITEBSTR( OLESTR("<PARAMETER.OBJECTARRAY NAME=\""))
|
|
WRITEBSTR( paramName)
|
|
WRITEBSTR( OLESTR("\" "))
|
|
MapStrongType (pOutputStream, pQualSet);
|
|
WRITEBSTR( OLESTR(" "))
|
|
MapArraySize (pOutputStream, pQualSet);
|
|
WRITEBSTR( OLESTR(">"))
|
|
WRITENEWLINE
|
|
|
|
// Map the qualifiers of the parameter
|
|
if (pQualSet || pQualSet2)
|
|
MapQualifiers (pOutputStream, pQualSet, pQualSet2);
|
|
|
|
WRITEBSTR( OLESTR("</PARAMETER.OBJECTARRAY>"))
|
|
}
|
|
else
|
|
{
|
|
WRITEBSTR( OLESTR("<PARAMETER.ARRAY NAME=\""))
|
|
WRITEBSTR( paramName)
|
|
WRITEBSTR( OLESTR("\" "))
|
|
MapType (pOutputStream, cimtype & ~CIM_FLAG_ARRAY);
|
|
WRITEBSTR( OLESTR(" "))
|
|
MapArraySize (pOutputStream, pQualSet);
|
|
WRITEBSTR( OLESTR(">"))
|
|
WRITENEWLINE
|
|
|
|
// Map the qualifiers of the parameter
|
|
if (pQualSet || pQualSet2)
|
|
MapQualifiers (pOutputStream, pQualSet, pQualSet2);
|
|
|
|
WRITEBSTR( OLESTR("</PARAMETER.ARRAY>"))
|
|
}
|
|
}
|
|
else if (cimtype == CIM_REFERENCE)
|
|
{
|
|
// Map the reference parameter
|
|
WRITEBSTR( OLESTR("<PARAMETER.REFERENCE NAME=\""))
|
|
WRITEBSTR( paramName)
|
|
WRITEBSTR( OLESTR("\" "))
|
|
MapStrongType (pOutputStream, pQualSet);
|
|
WRITEBSTR( OLESTR(">"))
|
|
WRITENEWLINE
|
|
|
|
// Map the qualifiers of the parameter
|
|
if (pQualSet || pQualSet2)
|
|
MapQualifiers (pOutputStream, pQualSet, pQualSet2);
|
|
|
|
WRITEBSTR( OLESTR("</PARAMETER.REFERENCE>"))
|
|
}
|
|
else if (cimtype == CIM_OBJECT)
|
|
{
|
|
WRITEBSTR( OLESTR("<PARAMETER.OBJECT NAME=\""))
|
|
WRITEBSTR( paramName)
|
|
WRITEBSTR( OLESTR("\" "))
|
|
MapStrongType (pOutputStream, pQualSet);
|
|
WRITEBSTR( OLESTR(">"))
|
|
WRITENEWLINE
|
|
|
|
// Map the qualifiers of the parameter
|
|
if (pQualSet || pQualSet2)
|
|
MapQualifiers (pOutputStream, pQualSet, pQualSet2);
|
|
|
|
WRITEBSTR( OLESTR("</PARAMETER.OBJECT>"))
|
|
}
|
|
else
|
|
{
|
|
// Vanilla parameter
|
|
WRITEBSTR( OLESTR("<PARAMETER NAME=\""))
|
|
WRITEBSTR( paramName)
|
|
WRITEBSTR( OLESTR("\" "))
|
|
MapType (pOutputStream, cimtype);
|
|
WRITEBSTR( OLESTR(">"))
|
|
WRITENEWLINE
|
|
|
|
// Map the qualifiers of the parameter
|
|
if (pQualSet || pQualSet2)
|
|
MapQualifiers (pOutputStream, pQualSet, pQualSet2);
|
|
|
|
WRITEBSTR( OLESTR("</PARAMETER>"))
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void CWmiToXml::MapByteValue (IStream *pOutputStream, unsigned char val)
|
|
{
|
|
OLECHAR wStr[32];
|
|
swprintf (wStr, L"%d", val);
|
|
WRITEBSTR( wStr)
|
|
}
|
|
|
|
void CWmiToXml::MapLongValue (IStream *pOutputStream, long val)
|
|
{
|
|
OLECHAR wStr[32];
|
|
swprintf (wStr, L"%d", val);
|
|
WRITEBSTR( wStr)
|
|
}
|
|
|
|
void CWmiToXml::MapShortValue (IStream *pOutputStream, short val)
|
|
{
|
|
OLECHAR wStr[32];
|
|
swprintf (wStr, L"%d", val);
|
|
WRITEBSTR( wStr)
|
|
}
|
|
|
|
void CWmiToXml::MapDoubleValue (IStream *pOutputStream, double val)
|
|
{
|
|
VARIANT varSrc,varDst;
|
|
VariantInit(&varSrc);
|
|
VariantInit(&varDst);
|
|
varSrc.vt = VT_R8;
|
|
varSrc.dblVal = val;
|
|
if(SUCCEEDED(VariantChangeType(&varDst,&varSrc,0,VT_BSTR)))
|
|
{
|
|
MapStringValue(pOutputStream,varDst.bstrVal);
|
|
}
|
|
VariantClear(&varSrc);
|
|
VariantClear(&varDst);
|
|
}
|
|
|
|
void CWmiToXml::MapFloatValue (IStream *pOutputStream, float val)
|
|
{
|
|
VARIANT varSrc,varDst;
|
|
VariantInit(&varDst);
|
|
VariantInit(&varSrc);
|
|
varSrc.vt = VT_R4;
|
|
varSrc.fltVal = val;
|
|
if(SUCCEEDED(VariantChangeType(&varDst,&varSrc,0,VT_BSTR)))
|
|
{
|
|
MapStringValue(pOutputStream,varDst.bstrVal);
|
|
}
|
|
VariantClear(&varSrc);
|
|
VariantClear(&varDst);
|
|
|
|
}
|
|
|
|
void CWmiToXml::MapCharValue (IStream *pOutputStream, long val)
|
|
{
|
|
// As per the XML Spec, the following are invalid character values in an XML Stream:
|
|
// Char ::= #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF]
|
|
|
|
// As per the CIM Operations spec, they need to be escaped as follows:
|
|
// If the value is not a legal XML character
|
|
// (as defined in [2, section 2.2] by the Char production)
|
|
// then it MUST be escaped using a \x<hex> escape convention
|
|
// where <hex> is a hexadecimal constant consisting of
|
|
// between one and four digits
|
|
|
|
if( val < 0x9 ||
|
|
(val == 0xB || val == 0xC) ||
|
|
(val > 0xD && val <0x20) ||
|
|
(val >0xD7FF && val < 0xE000) ||
|
|
(val > 0xFFFD)
|
|
)
|
|
{
|
|
// Map it in the escaped manner
|
|
OLECHAR charStr [7];
|
|
swprintf (charStr, L"\\x%04x", val&0xffff);
|
|
charStr[6] = NULL;
|
|
WRITEBSTR( charStr)
|
|
}
|
|
else
|
|
{
|
|
// FIrst check to see if is one of the reserved characters in XML - < & and >
|
|
// Map it in the normal manner
|
|
if(val == '<')
|
|
WRITELT
|
|
else if (val == '>')
|
|
WRITEGT
|
|
else if (val == '&')
|
|
WRITEAMP
|
|
else
|
|
{
|
|
// Map it in the normal manner
|
|
WCHAR charStr [2];
|
|
swprintf (charStr, L"%c", val);
|
|
charStr[1] = NULL;
|
|
WRITEBSTR(charStr)
|
|
}
|
|
}
|
|
}
|
|
|
|
void CWmiToXml::MapBoolValue (IStream *pOutputStream, BOOL val)
|
|
{
|
|
if (TRUE == val)
|
|
WRITEBSTR( OLESTR("TRUE"))
|
|
else
|
|
WRITEBSTR( OLESTR("FALSE"))
|
|
}
|
|
|
|
void CWmiToXml::MapStringValue (IStream *pOutputStream, BSTR &val)
|
|
{
|
|
/*
|
|
* Quote from http://www.w3.org/TR/REC-xml:
|
|
*
|
|
* The ampersand character (&) and the left angle bracket (<) may
|
|
* appear in their literal form only when used as markup delimiters,
|
|
* or within a comment, a processing instruction, or a CDATA section.
|
|
*
|
|
* If they are needed elsewhere, they must be escaped using either
|
|
* numeric character references or the strings "&" and "<"
|
|
* respectively.
|
|
*
|
|
* The right angle bracket (>) must, for compatibility, be escaped
|
|
* using ">" or a character reference when it appears in the string
|
|
* "]]>" in content, when that string is not marking the end of a CDATA
|
|
* section.
|
|
*
|
|
* In the content of elements, character data is any string of characters
|
|
* which does not contain the start-delimiter of any markup. In a CDATA
|
|
* section, character data is any string of characters not including the
|
|
* CDATA-section-close delimiter, "]]>".
|
|
*/
|
|
|
|
// Check that < or & do not occur in the value
|
|
size_t length = wcslen (val);
|
|
size_t offset = 0;
|
|
OLECHAR *pWchar = NULL;
|
|
|
|
if ((offset = wcscspn (val, L"<&")) < length)
|
|
{
|
|
// A reserved character (< &) appears in the value -
|
|
// need to escape. We can use CDATA if it does not
|
|
// contain the string ]]>
|
|
|
|
if (wcsstr (val, CDATAEND))
|
|
{
|
|
// Bad luck - can't use CDATA. Have to escape
|
|
// each reserved character and the CDATAEND sequence!
|
|
// Easiest way to do this is escape all occurences
|
|
// of >.
|
|
// < -> <
|
|
// & -> &
|
|
// > -> >
|
|
|
|
offset = wcscspn (val, L"<&>");
|
|
OLECHAR *pStr = (OLECHAR *)val;
|
|
|
|
while (TRUE)
|
|
{
|
|
// Write the initial block that's safe
|
|
if (offset > 0)
|
|
WRITEWSTRL( pStr, offset);
|
|
|
|
pStr += offset;
|
|
|
|
// Escape the offending character
|
|
if (L'<' == *pStr)
|
|
WRITELT
|
|
else if (L'>' == *pStr)
|
|
WRITEGT
|
|
else
|
|
WRITEAMP
|
|
|
|
// Skip over the reserved character
|
|
pStr += 1;
|
|
|
|
// Find the next position
|
|
if ((offset = wcscspn (pStr, L"<&>")) >= wcslen (pStr))
|
|
break;
|
|
}
|
|
|
|
// Any data left?
|
|
if (pStr && wcslen (pStr))
|
|
WRITEWSTR (pStr)
|
|
}
|
|
else
|
|
{
|
|
// Can escape the whole value inside a CDATA
|
|
WRITECDATASTART
|
|
WRITEBSTR( val)
|
|
WRITECDATAEND
|
|
}
|
|
}
|
|
else if (pWchar = wcsstr (val, CDATAEND))
|
|
{
|
|
// Yuck we need to escape the > inside this sequence
|
|
//
|
|
// ]]> -> ]]>
|
|
|
|
OLECHAR *pStr = (OLECHAR *)val;
|
|
|
|
while (TRUE)
|
|
{
|
|
offset = wcslen (pStr) - wcslen (pWchar);
|
|
|
|
// Write the initial block that's safe
|
|
// (NOTE: the additional two characters for the "]]"
|
|
// which we don't need to escape)
|
|
WRITEWSTRL( pStr,(offset+2));
|
|
|
|
// Skip over the CDATAEND sequence
|
|
pStr += offset + 3;
|
|
|
|
// Escape the offending character
|
|
WRITEGT
|
|
|
|
// Find the next position
|
|
if (!(pWchar = wcsstr (pStr, CDATAEND)))
|
|
break;
|
|
}
|
|
|
|
// Any data left?
|
|
if (pStr && wcslen (pStr))
|
|
WRITEWSTR (pStr)
|
|
}
|
|
else
|
|
{
|
|
// Just write the value
|
|
WRITEBSTR( val)
|
|
}
|
|
}
|
|
|
|
void CWmiToXml::MapReturnParameter(IStream *pOutputStream, BSTR strParameterName, VARIANT &variant)
|
|
{
|
|
// Could be a PARAMETER or PARAMETER.ARRAY
|
|
if(variant.vt & VT_ARRAY)
|
|
WRITEBSTR( OLESTR("<PARAMVALUE.ARRAY NAME=\""))
|
|
else
|
|
WRITEBSTR( OLESTR("<PARAMVALUE NAME=\""))
|
|
|
|
WRITEBSTR( strParameterName);
|
|
WRITEBSTR( OLESTR("\">"));
|
|
|
|
// Convert the property value to XML
|
|
MapValue(pOutputStream, variant);
|
|
if(variant.vt & VT_ARRAY)
|
|
WRITEBSTR( OLESTR("</PARAMVALUE.ARRAY>"))
|
|
else
|
|
WRITEBSTR( OLESTR("</PARAMVALUE>"))
|
|
}
|
|
|
|
|
|
BOOL CWmiToXml::PropertyDefinedForClass (IWbemClassObject *pObject, BSTR bsPropertyName, BSTR strClassBasis)
|
|
{
|
|
BOOL result = TRUE;
|
|
|
|
// Given (a) Class basis for enumeration and
|
|
// (b) property name, determine
|
|
// (1) CLASSORIGIN of property
|
|
// (2) Dynasty of class
|
|
// And thereby check whether property was defined
|
|
// at the level of the class basis.
|
|
// If no class basis is supplied, then we always return TRUE
|
|
//============================================================
|
|
if (strClassBasis && pObject)
|
|
{
|
|
// Get Property originating class
|
|
BSTR bsOrigClass = NULL;
|
|
|
|
if (SUCCEEDED (pObject->GetPropertyOrigin (bsPropertyName, &bsOrigClass)))
|
|
{
|
|
// Derivation is the Class hierarchy of the current class or instance.
|
|
// The first element is the immediate superclass, the next is its parent,
|
|
// and so on; the last element is the base class.
|
|
// Now work through the derivation array. If we meet the
|
|
// propertys' originating class before the class basis,
|
|
// we conclude that the property was not defined in the
|
|
// class basis
|
|
|
|
// If we have been give a class basis, get the __DERIVATION
|
|
// property for each object
|
|
VARIANT vDerivation;
|
|
VariantInit(&vDerivation);
|
|
if (SUCCEEDED(pObject->Get (L"__DERIVATION", 0, &vDerivation, NULL, NULL)))
|
|
{
|
|
SAFEARRAY *pArray = vDerivation.parray;
|
|
|
|
if (pArray && (1 == pArray->cDims) && (0 < pArray->rgsabound [0].cElements))
|
|
{
|
|
int lBound = pArray->rgsabound [0].lLbound;
|
|
int uBound = pArray->rgsabound [0].cElements + lBound;
|
|
BOOL bDone = FALSE;
|
|
|
|
for (long i = lBound; (i < uBound) && !bDone; i++)
|
|
{
|
|
BSTR bsClass = NULL;
|
|
|
|
if (SUCCEEDED (SafeArrayGetElement (pArray, &i, &bsClass)))
|
|
{
|
|
if (0 == _wcsicmp (bsOrigClass, bsClass))
|
|
{
|
|
result = FALSE;
|
|
bDone = TRUE;
|
|
}
|
|
else if (0 == _wcsicmp (strClassBasis, bsClass))
|
|
bDone = TRUE;
|
|
|
|
SysFreeString (bsClass);
|
|
}
|
|
}
|
|
}
|
|
VariantClear(&vDerivation);
|
|
}
|
|
|
|
SysFreeString (bsOrigClass);
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
// Functions of the IWbemXMLConvertor interface
|
|
HRESULT STDMETHODCALLTYPE CWmiToXml::MapObjectToXML(
|
|
/* [in] */ IWbemClassObject *pObject,
|
|
/* [in] */ BSTR *ppPropertyList, DWORD dwNumProperties,
|
|
/* [in] */ IWbemContext *pInputFlags,
|
|
/* [in] */ IStream *pOutputStream,
|
|
/* [in[ */ BSTR strClassBasis)
|
|
{
|
|
// Set private members from arguments
|
|
GetFlagsFromContext(pInputFlags);
|
|
|
|
HRESULT hr = WBEM_E_FAILED;
|
|
|
|
// Is this a class or an instance?
|
|
VARIANT var;
|
|
VariantInit (&var);
|
|
long flav = 0;
|
|
bool bIsClass = false;
|
|
if (SUCCEEDED (pObject->Get(L"__GENUS", 0, &var, NULL, &flav)))
|
|
bIsClass = (WBEM_GENUS_CLASS == var.lVal);
|
|
else
|
|
bIsClass = VARIANT_FALSE; // For now, assume that it is an instance. RAJESHR is this correct?
|
|
VariantClear (&var);
|
|
|
|
// Initalize the object path
|
|
VariantInit (&var);
|
|
|
|
// For pathLevelAnonymous (anonymous objects), we dont need anything more
|
|
// For pathLevelNamed (named objects), we only need __RELPATH for a class and __RELPATH for an instance
|
|
// For pathLevelLocal, I wish core team had some concept
|
|
// of machine-relative path, but they dont and hence we need the __PATH
|
|
// For pathLevelFull, we definitely need __PATH
|
|
LPWSTR lpszPath = NULL;
|
|
switch(m_iPathLevel)
|
|
{
|
|
case pathLevelAnonymous:
|
|
break;
|
|
case pathLevelNamed:
|
|
lpszPath = L"__RELPATH";
|
|
break;
|
|
default:
|
|
lpszPath = L"__PATH";
|
|
}
|
|
|
|
// Get the object path
|
|
ParsedObjectPath *pParsedPath = NULL;
|
|
CObjectPathParser pathParser;
|
|
if(m_iPathLevel != pathLevelAnonymous)
|
|
{
|
|
if(FAILED(pObject->Get (lpszPath, 0, &var, NULL, NULL)))
|
|
return WBEM_E_FAILED;
|
|
// Now Parse it
|
|
if ((VT_BSTR == var.vt) && (NULL != var.bstrVal) && (wcslen (var.bstrVal) > 0))
|
|
{
|
|
pathParser.Parse (var.bstrVal, &pParsedPath) ;
|
|
if(!pParsedPath)
|
|
{
|
|
VariantClear (&var);
|
|
return WBEM_E_FAILED;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
VariantClear (&var);
|
|
return WBEM_E_FAILED;
|
|
}
|
|
VariantClear (&var);
|
|
}
|
|
|
|
// Get the object Qualifier Set
|
|
IWbemQualifierSet *pQualSet= NULL;
|
|
pObject->GetQualifierSet (&pQualSet);
|
|
|
|
// Whether we generate a named object or not depends
|
|
// on what was requested
|
|
if (pathLevelNamed == m_iPathLevel)
|
|
{
|
|
if(!bIsClass)
|
|
MapInstanceName(pOutputStream, pParsedPath);
|
|
// Nothing to be done for a class
|
|
}
|
|
else if (pathLevelLocal == m_iPathLevel)
|
|
{
|
|
if(bIsClass)
|
|
MapLocalClassPath(pOutputStream, pParsedPath);
|
|
else
|
|
MapLocalInstancePath(pOutputStream, pParsedPath);
|
|
}
|
|
else if (pathLevelFull == m_iPathLevel)
|
|
{
|
|
if (bIsClass)
|
|
MapClassPath (pOutputStream, pParsedPath);
|
|
else
|
|
MapInstancePath (pOutputStream, pParsedPath);
|
|
}
|
|
|
|
hr = (bIsClass) ? MapClass (pOutputStream, pObject, pQualSet, ppPropertyList, dwNumProperties, strClassBasis) :
|
|
MapInstance (pOutputStream, pObject, pQualSet, ppPropertyList, dwNumProperties, strClassBasis);
|
|
|
|
|
|
if (pQualSet)
|
|
pQualSet->Release ();
|
|
if(pParsedPath)
|
|
pathParser.Free(pParsedPath);
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE CWmiToXml::MapInstanceNameToXML(
|
|
/* [in] */ BSTR strInstanceName,
|
|
/* [in] */ IWbemContext *pInputFlags,
|
|
/* [in] */ IStream *pOutputStream)
|
|
{
|
|
// Set private members from arguments
|
|
GetFlagsFromContext(pInputFlags);
|
|
|
|
HRESULT hr = WBEM_E_FAILED;
|
|
if (strInstanceName)
|
|
{
|
|
CObjectPathParser pathParser;
|
|
ParsedObjectPath *pParsedPath = NULL;
|
|
pathParser.Parse (strInstanceName, &pParsedPath) ;
|
|
|
|
if(pParsedPath)
|
|
{
|
|
hr = MapInstanceName (pOutputStream, pParsedPath);;
|
|
pathParser.Free(pParsedPath);
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE CWmiToXml::MapPropertyToXML(
|
|
/* [in] */ IWbemClassObject *pObject,
|
|
/* [in] */ BSTR strPropertyName,
|
|
/* [in] */ IWbemContext *pInputFlags,
|
|
/* [in] */ IStream *pOutputStream)
|
|
{
|
|
// Set private members from arguments
|
|
GetFlagsFromContext(pInputFlags);
|
|
|
|
VARIANT var;
|
|
VariantInit (&var);
|
|
CIMTYPE cimtype;
|
|
long flavor;
|
|
|
|
HRESULT hr = pObject->Get (strPropertyName, 0, &var, &cimtype, &flavor);
|
|
|
|
if (SUCCEEDED (hr))
|
|
{
|
|
if (CIM_REFERENCE == (cimtype & ~CIM_FLAG_ARRAY))
|
|
MapReferenceValue (pOutputStream, (cimtype & CIM_FLAG_ARRAY) ? TRUE : FALSE, var);
|
|
else
|
|
MapValue (pOutputStream, cimtype & ~CIM_FLAG_ARRAY, (cimtype & CIM_FLAG_ARRAY) ?
|
|
TRUE : FALSE, var);
|
|
}
|
|
|
|
VariantClear (&var);
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT STDMETHODCALLTYPE CWmiToXml::MapClassNameToXML(
|
|
/* [in] */ BSTR strClassName,
|
|
/* [in] */ IWbemContext *pInputFlags,
|
|
/* [in] */ IStream *pOutputStream)
|
|
{
|
|
MapClassName(pOutputStream, strClassName);
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE CWmiToXml::MapInstancePathToXML(
|
|
/* [in] */ BSTR strInstancePath,
|
|
/* [in] */ IWbemContext *pInputFlags,
|
|
/* [in] */ IStream *pOutputStream)
|
|
{
|
|
// Set private members from arguments
|
|
GetFlagsFromContext(pInputFlags);
|
|
|
|
HRESULT hr = WBEM_E_FAILED;
|
|
if (strInstancePath)
|
|
{
|
|
CObjectPathParser pathParser;
|
|
ParsedObjectPath *pParsedPath = NULL;
|
|
pathParser.Parse (strInstancePath, &pParsedPath) ;
|
|
|
|
if (pParsedPath)
|
|
{
|
|
hr = MapInstancePath (pOutputStream, pParsedPath);;
|
|
pathParser.Free(pParsedPath);
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE CWmiToXml::MapClassPathToXML(
|
|
/* [in] */ BSTR strClassPath,
|
|
/* [in] */ IWbemContext *pInputFlags,
|
|
/* [in] */ IStream *pOutputStream)
|
|
{
|
|
// Set private members from arguments
|
|
GetFlagsFromContext(pInputFlags);
|
|
|
|
HRESULT hr = WBEM_E_FAILED;
|
|
if (strClassPath)
|
|
{
|
|
CObjectPathParser pathParser;
|
|
ParsedObjectPath *pParsedPath = NULL;
|
|
pathParser.Parse (strClassPath, &pParsedPath) ;
|
|
|
|
if (pParsedPath)
|
|
{
|
|
hr = MapClassPath (pOutputStream, pParsedPath);;
|
|
pathParser.Free(pParsedPath);
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE CWmiToXml::MapMethodResultToXML(
|
|
/* [in] */ IWbemClassObject *pMethodResult,
|
|
/* [in] */ IWbemContext *pInputFlags,
|
|
/* [in] */ IStream *pOutputStream)
|
|
{
|
|
// Set private members from arguments
|
|
GetFlagsFromContext(pInputFlags);
|
|
|
|
HRESULT hr = WBEM_E_FAILED;
|
|
|
|
// First Map the return Value
|
|
// The property "ReturnValue" indicates the return value of the method call, if any
|
|
VARIANT retValueVariant;
|
|
VariantInit(&retValueVariant);
|
|
CIMTYPE cimtype;
|
|
long flavour;
|
|
if(SUCCEEDED(pMethodResult->Get(L"ReturnValue", 0, &retValueVariant, &cimtype, &flavour)))
|
|
{
|
|
WRITEBSTR( OLESTR("<RETURNVALUE>"));
|
|
MapValue(pOutputStream, retValueVariant);
|
|
WRITEBSTR( OLESTR("</RETURNVALUE>"));
|
|
VariantClear(&retValueVariant);
|
|
}
|
|
|
|
// Map each of its non-system properties, except for the "ReturnValue" property which
|
|
// we've already mapped
|
|
if(SUCCEEDED(hr = pMethodResult->BeginEnumeration(WBEM_FLAG_NONSYSTEM_ONLY)))
|
|
{
|
|
BSTR strName = NULL;
|
|
VARIANT variant;
|
|
VariantInit(&variant);
|
|
while(SUCCEEDED(hr = pMethodResult->Next(0, &strName, &variant, &cimtype, &flavour)) && hr != WBEM_S_NO_MORE_DATA)
|
|
{
|
|
if(_wcsicmp(strName, L"ReturnValue") != 0)
|
|
MapReturnParameter(pOutputStream, strName, variant);
|
|
VariantClear(&variant);
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
// Get all the flags from the IWbemContextObject
|
|
void CWmiToXml::GetFlagsFromContext(IWbemContext *pInputFlags)
|
|
{
|
|
if(pInputFlags)
|
|
{
|
|
if(SUCCEEDED(pInputFlags->BeginEnumeration(0)))
|
|
{
|
|
VARIANT vNextArgValue;
|
|
VariantInit(&vNextArgValue);
|
|
BSTR strNextArgName = NULL;
|
|
|
|
while(pInputFlags->Next(0, &strNextArgName, &vNextArgValue) != WBEM_S_NO_MORE_DATA)
|
|
{
|
|
// VARIANT_BOOL bAllowWMIExtensions,
|
|
if(_wcsicmp(s_wmiToXmlArgs[WMI_EXTENSIONS_ARG], strNextArgName) == 0)
|
|
m_bAllowWMIExtensions = vNextArgValue.boolVal;
|
|
|
|
// VARIANT_BOOL bLocalOnly,
|
|
else if(_wcsicmp(s_wmiToXmlArgs[LOCAL_ONLY_ARG], strNextArgName) == 0)
|
|
m_bLocalOnly = vNextArgValue.boolVal;
|
|
|
|
// PathLevel m_iPathLevel;
|
|
else if(_wcsicmp(s_wmiToXmlArgs[PATH_LEVEL_ARG], strNextArgName) == 0)
|
|
m_iPathLevel = (PathLevel)vNextArgValue.lVal;
|
|
|
|
// WmiXMLQualifierFilterEnum m_iQualifierFilter
|
|
else if(_wcsicmp(s_wmiToXmlArgs[QUALIFIER_FILTER_ARG], strNextArgName) == 0)
|
|
m_iQualifierFilter = (vNextArgValue.boolVal == VARIANT_TRUE)? wmiXMLQualifierFilterAll : wmiXMLQualifierFilterNone;
|
|
|
|
// WmiXMLClassOriginFilterEnum iClassOriginFilter
|
|
else if(_wcsicmp(s_wmiToXmlArgs[CLASS_ORIGIN_FILTER_ARG], strNextArgName) == 0)
|
|
m_iClassOriginFilter = (vNextArgValue.boolVal == VARIANT_TRUE) ? wmiXMLClassOriginFilterAll : wmiXMLClassOriginFilterNone;
|
|
|
|
// VARIANT_BOOL bExcludeSystemProperties
|
|
else if(_wcsicmp(s_wmiToXmlArgs[EXCLUDE_SYSTEM_PROPERTIES_ARG], strNextArgName) == 0)
|
|
m_bExcludeSystemProperties = vNextArgValue.boolVal;
|
|
|
|
VariantClear(&vNextArgValue);
|
|
}
|
|
pInputFlags->EndEnumeration();
|
|
}
|
|
}
|
|
}
|
|
|
|
|