535 lines
16 KiB
C++
535 lines
16 KiB
C++
//***************************************************************************
|
|
//
|
|
// Copyright (c) 2000-2001 Microsoft Corporation
|
|
//
|
|
// DSERLZER.CPP
|
|
//
|
|
// rajeshr 08-Jan-01 Created.
|
|
//
|
|
// WMI XSD Deserializer implementation. Server side only.
|
|
//
|
|
//***************************************************************************
|
|
|
|
#include "precomp.h"
|
|
|
|
// Element Names
|
|
//================================================
|
|
static LPCWSTR WMI_XML_ELEMENT = L"element";
|
|
static LPCWSTR WMI_XML_COMPLEX_TYPE= L"complexType";
|
|
static LPCWSTR WMI_XML_PROPERTY = L"property";
|
|
static LPCWSTR WMI_XML_METHOD = L"method";
|
|
static LPCWSTR WMI_XML_QUALIFIER = L"qualifier";
|
|
|
|
// Attribute Names
|
|
//=======================================
|
|
static LPCWSTR WMI_XML_NAME = L"name";
|
|
static int WMI_XML_NAME_LEN = 4;
|
|
static LPCWSTR WMI_XML_BASE = L"base";
|
|
static int WMI_XML_BASE_LEN = 4;
|
|
static LPCWSTR WMI_XML_TYPE = L"type";
|
|
static int WMI_XML_TYPE_LEN = 4;
|
|
static LPCWSTR WMI_XML_VALUE = L"value";
|
|
static int WMI_XML_VALUE_LEN = 5;
|
|
// Qualifier flavor attributes
|
|
static LPCWSTR WMI_XML_TOSUBCLASS = L"toSubclass";
|
|
static int WMI_XML_TOSUBCLASS_LEN = 10;
|
|
static LPCWSTR WMI_XML_TOINSTANCE = L"toInstance";
|
|
static int WMI_XML_TOINSTANCE_LEN = 10;
|
|
static LPCWSTR WMI_XML_OVERRIDABLE = L"overridable";
|
|
static int WMI_XML_OVERRIDABLE_LEN = 11;
|
|
static LPCWSTR WMI_XML_AMENDED = L"amended";
|
|
static int WMI_XML_AMENDED_LEN = 7;
|
|
static LPCWSTR WMI_XML_ARRAY = L"array";
|
|
static int WMI_XML_ARRAY_LEN = 5;
|
|
|
|
|
|
CWmiDeserializer::CWmiDeserializer(IWbemServices *pServices) :
|
|
m_cRef (1),
|
|
m_bIsClass (FALSE)
|
|
{
|
|
m_pIWbemServices = pServices;
|
|
m_pIWbemServices->AddRef();
|
|
|
|
m_pIWbemClassObject = NULL;
|
|
m_strSuperClassName = m_strClassName = m_strPropertyName = m_strMethodName = m_strQualifierName = NULL;
|
|
|
|
m_pObjectQualifierSet = NULL;
|
|
m_pPropertyQualifierSet = NULL;
|
|
m_pMethodQualifierSet = NULL;
|
|
|
|
m_iParserState = INVALID;
|
|
}
|
|
|
|
CWmiDeserializer::~CWmiDeserializer()
|
|
{
|
|
m_pIWbemServices->Release();
|
|
|
|
if(m_pIWbemClassObject)
|
|
m_pIWbemClassObject->Release();
|
|
if(m_pObjectQualifierSet)
|
|
m_pObjectQualifierSet->Release();
|
|
if(m_pPropertyQualifierSet)
|
|
m_pPropertyQualifierSet->Release();
|
|
if(m_pMethodQualifierSet)
|
|
m_pMethodQualifierSet->Release();
|
|
|
|
SysFreeString(m_strSuperClassName);
|
|
SysFreeString(m_strClassName);
|
|
SysFreeString(m_strPropertyName);
|
|
SysFreeString(m_strMethodName);
|
|
SysFreeString(m_strQualifierName);
|
|
}
|
|
|
|
STDMETHODIMP CWmiDeserializer::QueryInterface (
|
|
|
|
IN REFIID riid,
|
|
OUT LPVOID *ppv
|
|
)
|
|
{
|
|
*ppv=NULL;
|
|
|
|
if (IID_IUnknown==riid)
|
|
*ppv = reinterpret_cast<IUnknown*>(this);
|
|
else if (__uuidof(ISAXContentHandler)==riid)
|
|
*ppv = (ISAXContentHandler *)this;
|
|
else if (__uuidof(ISAXErrorHandler)==riid)
|
|
*ppv = (ISAXErrorHandler *)this;
|
|
else if (__uuidof(ISAXLexicalHandler)==riid)
|
|
*ppv = (ISAXLexicalHandler *)this;
|
|
|
|
if (NULL!=*ppv)
|
|
{
|
|
((LPUNKNOWN)*ppv)->AddRef();
|
|
return NOERROR;
|
|
}
|
|
|
|
return ResultFromScode(E_NOINTERFACE);
|
|
}
|
|
|
|
STDMETHODIMP_(ULONG) CWmiDeserializer::AddRef(void)
|
|
{
|
|
InterlockedIncrement(&m_cRef);
|
|
return m_cRef;
|
|
}
|
|
|
|
STDMETHODIMP_(ULONG) CWmiDeserializer::Release(void)
|
|
{
|
|
LONG cRef = InterlockedDecrement(&m_cRef);
|
|
|
|
if (0L!=cRef)
|
|
return cRef;
|
|
|
|
delete this;
|
|
return 0;
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE CWmiDeserializer::Deserialize (
|
|
BOOL bIsClass,
|
|
IWbemServices *pIWbemServices,
|
|
IWbemClassObject **ppIWbemClassObject)
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE CWmiDeserializer::startDocument()
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE CWmiDeserializer::endDocument ( )
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE CWmiDeserializer::startElement(
|
|
const wchar_t __RPC_FAR *pwchNamespaceUri,
|
|
int cchNamespaceUri,
|
|
const wchar_t __RPC_FAR *pwchLocalName,
|
|
int cchLocalName,
|
|
const wchar_t __RPC_FAR *pwchRawName,
|
|
int cchRawName,
|
|
ISAXAttributes __RPC_FAR *pAttributes)
|
|
{
|
|
HRESULT result = E_FAIL;
|
|
|
|
// A Complex Type
|
|
if (0 == wcscmp(WMI_XML_COMPLEX_TYPE, pwchLocalName))
|
|
{
|
|
// We need to get the name of the class and the superclass
|
|
if(SUCCEEDED(result = GetAttributeValue(pAttributes, WMI_XML_NAME, WMI_XML_NAME_LEN, &m_strClassName)))
|
|
{
|
|
// Get a superclass if any. This is an optional attribute
|
|
GetAttributeValue(pAttributes, WMI_XML_BASE, WMI_XML_BASE_LEN, &m_strSuperClassName);
|
|
|
|
// Get an IWbemClassObject that corresponds to the super class or is an empty class
|
|
IWbemClassObject *pSuperClass = NULL;
|
|
if(SUCCEEDED(result = m_pIWbemServices->GetObject(m_strSuperClassName, 0, NULL, &pSuperClass, NULL)))
|
|
{
|
|
result = pSuperClass->SpawnDerivedClass(0, &m_pIWbemClassObject);
|
|
pSuperClass->Release();
|
|
}
|
|
}
|
|
}
|
|
// AppInfo Section - This usually comes before the Properties
|
|
// We have certain important pieces of information in the AppInfo section including:
|
|
// 1. Property Qualifiers
|
|
// 2. Property default values
|
|
// 3. Object Qualifiers
|
|
// However, the actual property types come only in the body of the complex type.
|
|
// Since we're using SAX, we need to store the AppInfo section information somewhere until
|
|
// we get the property type. We can use a hash table, but the method adopted here
|
|
// is to use the IWbemClassObject itself as a bag of properties. Until we actually get the
|
|
// property type from the Properties section, we assume that the type of the property is
|
|
// VT_BSTR
|
|
|
|
// A property or or method object qualifier
|
|
else if (0 == wcscmp(WMI_XML_QUALIFIER, pwchLocalName))
|
|
{
|
|
if(m_pIWbemClassObject)
|
|
{
|
|
// Convert the XML Qualifier attributes to a WMI Qualifier
|
|
//===========================================================
|
|
BSTR strName = NULL;
|
|
VARIANT vValue;
|
|
VariantInit(&vValue);
|
|
LONG lFlavor = 0;
|
|
if(SUCCEEDED(result = ConvertQualifierToWMI(pAttributes, &strName, &vValue, lFlavor)))
|
|
{
|
|
// Is it a Property qualifier?
|
|
if(m_iParserState == APPINFO_PROPERTY)
|
|
{
|
|
// Get a Qualifier Set for the property, if we dont already have one
|
|
if(!m_pPropertyQualifierSet)
|
|
result = m_pIWbemClassObject->GetPropertyQualifierSet(m_strPropertyName, &m_pPropertyQualifierSet);
|
|
|
|
if(SUCCEEDED(result))
|
|
result = m_pPropertyQualifierSet->Put(strName, &vValue, lFlavor);
|
|
}
|
|
// Is it a Method qualifier?
|
|
if(m_iParserState == APPINFO_METHOD)
|
|
{
|
|
// Get a Qualifier Set for the property, if we dont already have one
|
|
if(!m_pMethodQualifierSet)
|
|
result = m_pIWbemClassObject->GetMethodQualifierSet(m_strMethodName, &m_pMethodQualifierSet);
|
|
|
|
if(SUCCEEDED(result))
|
|
result = m_pMethodQualifierSet->Put(strName, &vValue, lFlavor);
|
|
}
|
|
else // It is an object qualifier
|
|
{
|
|
// Get a Qualifier Set for the object, if we dont already have one
|
|
if(!m_pObjectQualifierSet)
|
|
result = m_pIWbemClassObject->GetQualifierSet(&m_pObjectQualifierSet);
|
|
|
|
if(SUCCEEDED(result))
|
|
result = m_pObjectQualifierSet->Put(strName, &vValue, lFlavor);
|
|
}
|
|
|
|
SysFreeString(strName);
|
|
VariantClear(&vValue);
|
|
// No need to release the qualifier set since we will most likely need it for
|
|
// adding another qualifier
|
|
|
|
}
|
|
}
|
|
}
|
|
// A Property
|
|
else if (0 == wcscmp(WMI_XML_PROPERTY, pwchLocalName))
|
|
{
|
|
if(m_pIWbemClassObject)
|
|
{
|
|
|
|
m_iParserState = APPINFO_PROPERTY;
|
|
|
|
// Create a property of type VT_BSTR provisonally in the object,
|
|
// so that we can get the qualifier set
|
|
|
|
// Free any existing data in our temporary variables
|
|
SysFreeString(m_strPropertyName);
|
|
m_strPropertyName = NULL;
|
|
|
|
// Get the name of the property
|
|
if(SUCCEEDED(result = GetAttributeValue(pAttributes, WMI_XML_NAME, WMI_XML_NAME_LEN, &m_strPropertyName)))
|
|
{
|
|
if(SUCCEEDED(result = m_pIWbemClassObject->Put(m_strPropertyName, 0, NULL, CIM_STRING)))
|
|
{
|
|
// Release any Qualifier Set currently being held
|
|
if(m_pPropertyQualifierSet)
|
|
{
|
|
m_pPropertyQualifierSet->Release();
|
|
m_pPropertyQualifierSet = NULL;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// A Method
|
|
else if (0 == wcscmp(WMI_XML_METHOD, pwchLocalName))
|
|
{
|
|
if(m_pIWbemClassObject)
|
|
{
|
|
|
|
m_iParserState = APPINFO_METHOD;
|
|
|
|
// Create a Method of type "void f()" provisonally in the object,
|
|
// so that we can get the qualifier set
|
|
|
|
// Free any existing data in our temporary variables
|
|
SysFreeString(m_strMethodName);
|
|
m_strMethodName = NULL;
|
|
|
|
// Get the name of the property
|
|
if(SUCCEEDED(result = GetAttributeValue(pAttributes, WMI_XML_NAME, WMI_XML_NAME_LEN, &m_strMethodName)))
|
|
{
|
|
if(SUCCEEDED(result = m_pIWbemClassObject->PutMethod(m_strMethodName, 0, NULL, NULL)))
|
|
{
|
|
// Release any Qualifier Set currently being held
|
|
if(m_pMethodQualifierSet)
|
|
{
|
|
m_pMethodQualifierSet->Release();
|
|
m_pMethodQualifierSet = NULL;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// Properties in the body of the complex type
|
|
else if (0 == wcscmp(WMI_XML_ELEMENT, pwchLocalName))
|
|
{
|
|
if(m_pIWbemClassObject)
|
|
{
|
|
m_iParserState = BODY_ELEMENT;
|
|
// Get the Name of the property
|
|
BSTR strName = NULL;
|
|
if(SUCCEEDED(result = GetAttributeValue(pAttributes, WMI_XML_NAME, WMI_XML_NAME_LEN, &strName)))
|
|
{
|
|
// Get the Type of the property
|
|
BSTR strType = NULL;
|
|
if(SUCCEEDED(result = GetAttributeValue(pAttributes, WMI_XML_TYPE, WMI_XML_TYPE_LEN, &strType)))
|
|
{
|
|
// Set the actual type of the property
|
|
result = RectifyProperty(m_pIWbemClassObject, strName, strType);
|
|
|
|
SysFreeString(strType);
|
|
}
|
|
SysFreeString(strName);
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
HRESULT CWmiDeserializer::GetAttributeValue(ISAXAttributes *pAttributes,
|
|
LPCWSTR lpAttributeName, int iAttributeNameLen,
|
|
BSTR *pstrAttributeValue)
|
|
{
|
|
HRESULT result = E_FAIL;
|
|
|
|
int iAttributeIndex = 0;
|
|
// Get the index of the attribute
|
|
if(SUCCEEDED(result = pAttributes->getIndexFromName(NULL, 0, lpAttributeName, iAttributeNameLen, &iAttributeIndex)))
|
|
{
|
|
// Get the Value of the attribute
|
|
int iAttributeValueLength = 0;
|
|
LPCWSTR lpAttributeValue = NULL;
|
|
if(SUCCEEDED(result = pAttributes->getValue(iAttributeIndex, &lpAttributeValue, &iAttributeValueLength)))
|
|
{
|
|
// Convert it to BSTR for returning
|
|
if (*pstrAttributeValue = SysAllocStringLen(lpAttributeValue, iAttributeValueLength))
|
|
result = S_OK;
|
|
else
|
|
result = E_OUTOFMEMORY;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
|
|
HRESULT STDMETHODCALLTYPE CWmiDeserializer::endElement (
|
|
const wchar_t * pwchNamespaceUri,
|
|
int cchNamespaceUri,
|
|
const wchar_t * pwchLocalName,
|
|
int cchLocalName,
|
|
const wchar_t * pwchQName,
|
|
int cchQName )
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE CWmiDeserializer::characters (
|
|
const unsigned short * pwchChars,
|
|
int cchChars )
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
// A method to set the type of a property to the correct type
|
|
HRESULT CWmiDeserializer::RectifyProperty(IWbemClassObject *pIWbemClassObject, BSTR strName, BSTR strType)
|
|
{
|
|
HRESULT result = E_FAIL;
|
|
return result;
|
|
}
|
|
|
|
HRESULT CWmiDeserializer::ConvertQualifierToWMI(ISAXAttributes * pAttributes,
|
|
BSTR *pstrName,
|
|
VARIANT *pValue,
|
|
LONG& lQualifierFlavor)
|
|
{
|
|
lQualifierFlavor = WBEM_FLAVOR_FLAG_PROPAGATE_TO_DERIVED_CLASS; // The default
|
|
HRESULT result = S_OK;
|
|
|
|
// Get its Name, Type and Value - These are mandatory attributes
|
|
//==============================================================
|
|
pstrName = NULL;
|
|
BSTR strType = NULL;
|
|
BSTR strValue = NULL;
|
|
BSTR strArray = NULL;
|
|
bool bIsArray = false;
|
|
|
|
if(SUCCEEDED(result = GetAttributeValue(pAttributes, WMI_XML_NAME, WMI_XML_NAME_LEN, pstrName)))
|
|
{
|
|
if(SUCCEEDED(result = GetAttributeValue(pAttributes, WMI_XML_TYPE, WMI_XML_TYPE_LEN, &strType)))
|
|
{
|
|
if(SUCCEEDED(result = GetAttributeValue(pAttributes, WMI_XML_VALUE, WMI_XML_VALUE_LEN, &strValue)))
|
|
{
|
|
// Now get the optional attributes
|
|
// These are the qualifier flavors and the "array" attribute
|
|
//============================================================
|
|
BSTR strArray = NULL;
|
|
if(SUCCEEDED(result = GetAttributeValue(pAttributes, WMI_XML_ARRAY, WMI_XML_ARRAY_LEN, &strArray)))
|
|
{
|
|
if(wcscmp(strArray, L"true") == 0)
|
|
bIsArray = true;
|
|
SysFreeString(strArray);
|
|
}
|
|
|
|
BSTR strFlavorValue = NULL;
|
|
if(SUCCEEDED(result = GetAttributeValue(pAttributes, WMI_XML_TOSUBCLASS, WMI_XML_TOSUBCLASS_LEN, &strFlavorValue)))
|
|
{
|
|
if(wcscmp(strFlavorValue, L"false") == 0)
|
|
lQualifierFlavor &= (~WBEM_FLAVOR_FLAG_PROPAGATE_TO_DERIVED_CLASS); // Remove the default flag set
|
|
SysFreeString(strFlavorValue);
|
|
}
|
|
if(SUCCEEDED(result = GetAttributeValue(pAttributes, WMI_XML_TOINSTANCE, WMI_XML_TOINSTANCE_LEN, &strFlavorValue)))
|
|
{
|
|
if(wcscmp(strFlavorValue, L"true") == 0)
|
|
lQualifierFlavor |= WBEM_FLAVOR_FLAG_PROPAGATE_TO_INSTANCE;
|
|
SysFreeString(strFlavorValue);
|
|
}
|
|
if(SUCCEEDED(result = GetAttributeValue(pAttributes, WMI_XML_OVERRIDABLE, WMI_XML_OVERRIDABLE_LEN, &strFlavorValue)))
|
|
{
|
|
if(wcscmp(strFlavorValue, L"true") == 0)
|
|
lQualifierFlavor |= WBEM_FLAVOR_OVERRIDABLE;
|
|
SysFreeString(strFlavorValue);
|
|
}
|
|
if(SUCCEEDED(result = GetAttributeValue(pAttributes, WMI_XML_AMENDED, WMI_XML_AMENDED_LEN, &strFlavorValue)))
|
|
{
|
|
if(wcscmp(strFlavorValue, L"true") == 0)
|
|
lQualifierFlavor |= WBEM_FLAVOR_AMENDED;
|
|
SysFreeString(strFlavorValue);
|
|
}
|
|
|
|
// Now convert the value of the Qualifier to a Variant
|
|
result = ConvertQualifierValueToWMI(strType, bIsArray, strValue, pValue);
|
|
SysFreeString(strValue);
|
|
|
|
}
|
|
else
|
|
result = WBEM_E_INVALID_SYNTAX;
|
|
SysFreeString(strType);
|
|
}
|
|
else
|
|
result = WBEM_E_INVALID_SYNTAX;
|
|
}
|
|
else
|
|
result = WBEM_E_INVALID_SYNTAX;
|
|
return result;
|
|
}
|
|
|
|
HRESULT CWmiDeserializer::ConvertQualifierValueToWMI(BSTR strType, bool bIsArray, BSTR strValue, VARIANT *pValue)
|
|
{
|
|
HRESULT result = WBEM_E_INVALID_SYNTAX;
|
|
|
|
// Check if it is an array
|
|
if(bIsArray)
|
|
pValue->vt |= VT_ARRAY;
|
|
|
|
// Qualifier values in WMI can be of 4 types
|
|
//==========================================
|
|
if(wcscmp(strType, L"boolean") == 0)
|
|
{
|
|
pValue->vt |= VT_BOOL;
|
|
if(bIsArray)
|
|
result = ConvertBooleanQualifierArray(pValue, strValue);
|
|
else
|
|
{
|
|
if(wcscmp(strValue, L"true") == 0)
|
|
pValue->boolVal = VARIANT_TRUE;
|
|
else // Do I need to match the value to "false" ?
|
|
pValue->boolVal = VARIANT_FALSE;
|
|
result = S_OK;
|
|
}
|
|
}
|
|
else if(wcscmp(strType, L"string") == 0)
|
|
{
|
|
pValue->vt |= VT_BSTR;
|
|
if(bIsArray)
|
|
result = ConvertStringQualifierArray(pValue, strValue);
|
|
else
|
|
{
|
|
if(pValue->bstrVal = SysAllocString(strValue))
|
|
result = S_OK;
|
|
else
|
|
result = E_OUTOFMEMORY;
|
|
}
|
|
}
|
|
else if(wcscmp(strType, L"sint32") == 0)
|
|
{
|
|
if(bIsArray)
|
|
result = ConvertSint32QualifierArray(pValue, strValue);
|
|
else
|
|
{
|
|
pValue->vt |= VT_I4;
|
|
pValue->lVal = wcstol (strValue, NULL, 0);
|
|
}
|
|
}
|
|
else if(wcscmp(strType, L"real64") == 0)
|
|
{
|
|
if(bIsArray)
|
|
result = ConvertReal64QualifierArray(pValue, strValue);
|
|
else
|
|
{
|
|
pValue->vt |= VT_R8;
|
|
pValue->dblVal = wcstod (strValue, NULL);
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
HRESULT CWmiDeserializer::ConvertBooleanQualifierArray(VARIANT *pValue, BSTR strValue)
|
|
{
|
|
HRESULT result = WBEM_E_INVALID_SYNTAX;
|
|
return result;
|
|
}
|
|
|
|
HRESULT CWmiDeserializer::ConvertStringQualifierArray(VARIANT *pValue, BSTR strValue)
|
|
{
|
|
HRESULT result = WBEM_E_INVALID_SYNTAX;
|
|
return result;
|
|
}
|
|
|
|
HRESULT CWmiDeserializer::ConvertSint32QualifierArray(VARIANT *pValue, BSTR strValue)
|
|
{
|
|
HRESULT result = WBEM_E_INVALID_SYNTAX;
|
|
return result;
|
|
}
|
|
|
|
HRESULT CWmiDeserializer::ConvertReal64QualifierArray(VARIANT *pValue, BSTR strValue)
|
|
{
|
|
HRESULT result = WBEM_E_INVALID_SYNTAX;
|
|
return result;
|
|
}
|
|
|