//*************************************************************************** // // (c) 1999 by Microsoft Corporation // // XML2WMI.CPP // // alanbos 09-Jul-99 Created. // // The XML -> WMI translator // //*************************************************************************** #include <windows.h> #include <stdio.h> #include <objbase.h> #include <wbemidl.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 "concache.h" #include "wmiconv.h" #include "xml2wmi.h" #include "wmixmlt.h" #include "request.h" #include "strings.h" #include "xmlhelp.h" #include "parse.h" //*************************************************************************** // // CXmlToWmi::CXmlToWmi // // DESCRIPTION: // // Constructor // //*************************************************************************** CXmlToWmi::CXmlToWmi () { m_pXml = NULL; m_pWmiObject = NULL; m_pServices = NULL; } HRESULT CXmlToWmi::Initialize (IXMLDOMNode *pXml, IWbemServices *pServices, IWbemClassObject *pWmiObject) { if (m_pXml = pXml) m_pXml->AddRef (); if (m_pWmiObject = pWmiObject) m_pWmiObject->AddRef (); if (m_pServices = pServices) m_pServices->AddRef (); return S_OK; } //*************************************************************************** // // CXmlToWmi::~CXmlToWmi // // DESCRIPTION: // // Destructor. // //*************************************************************************** CXmlToWmi::~CXmlToWmi(void) { if (m_pXml) m_pXml->Release (); if (m_pWmiObject) m_pWmiObject->Release (); if(m_pServices) m_pServices->Release(); } HRESULT CXmlToWmi::MapClassName (BSTR *pstrClassName) { HRESULT hr = WBEM_E_FAILED; *pstrClassName = NULL; if(SUCCEEDED(hr = GetBstrAttribute(m_pXml, NAME_ATTRIBUTE, pstrClassName))) { VARIANT value; VariantInit (&value); value.vt = VT_BSTR; value.bstrVal = *pstrClassName; hr = m_pWmiObject->Put (L"__CLASS", 0, &value, VT_BSTR); value.bstrVal = NULL; VariantClear (&value); } return hr; } //*************************************************************************** // // HRESULT CXmlToWmi::MapClass // // DESCRIPTION: // // Maps an XML <CLASS> into its WMI IWbemClassObject equivalent form // // PARAMETERS: // // // RETURN VALUES: // // //*************************************************************************** HRESULT CXmlToWmi::MapClass ( bool bIsModify ) { HRESULT hr = S_OK; if(m_pXml && m_pWmiObject) { IWbemQualifierSet *pQualSet = NULL; if (SUCCEEDED(m_pWmiObject->GetQualifierSet (&pQualSet))) { BSTR strClassName = NULL; if (SUCCEEDED(hr = MapClassName (&strClassName))) { VARIANT_BOOL bHasChildNodes; if (SUCCEEDED(m_pXml->hasChildNodes (&bHasChildNodes)) && (VARIANT_TRUE == bHasChildNodes)) { IXMLDOMNodeList *pNodeList = NULL; if (SUCCEEDED(m_pXml->get_childNodes (&pNodeList))) { IXMLDOMNode *pNode = NULL; while (SUCCEEDED(hr) && SUCCEEDED(pNodeList->nextNode (&pNode)) &&pNode) { // Get the Name of the property/method/qualifier // We dont need to map system properties that begin with "__" bool bMapElement = false; BSTR strName = NULL; if(SUCCEEDED(hr = GetBstrAttribute(pNode, NAME_ATTRIBUTE, &strName))) { // See if it is one of the System Properties if(_wcsnicmp(strName, L"__", 2) != 0) bMapElement = true; SysFreeString(strName); } // This element should be mapped only if it was defined/modified // in the current class. Hence get its class origin information // If there's no class origin information, assume that it is defined in // the current class BSTR strClassOrigin = NULL; if(bMapElement && SUCCEEDED(hr = GetBstrAttribute(pNode, CLASS_ORIGIN_ATTRIBUTE, &strClassOrigin)) && strClassOrigin) { if(_wcsicmp(strClassOrigin, strClassName) != 0) bMapElement = false; SysFreeString(strClassOrigin); } if(bMapElement) { BSTR strNodeName = NULL; if (SUCCEEDED(pNode->get_nodeName (&strNodeName))) { if (0 == _wcsicmp(strNodeName, QUALIFIER_TAG)) hr = MapQualifier (pNode, pQualSet); else if (0 == _wcsicmp(strNodeName, PROPERTY_TAG)) hr = MapProperty (pNode, false, bIsModify); else if (0 == _wcsicmp(strNodeName, PROPERTYARRAY_TAG)) hr = MapProperty (pNode, true, bIsModify); else if (0 == _wcsicmp(strNodeName, PROPERTYREFERENCE_TAG)) hr = MapPropertyReference (pNode, false, bIsModify); else if (0 == _wcsicmp(strNodeName, PROPERTYREFARRAY_TAG)) hr = MapPropertyReference (pNode, true, bIsModify); else if (0 == _wcsicmp(strNodeName, PROPERTYOBJECT_TAG)) hr = MapPropertyObject (pNode, false, bIsModify); else if (0 == _wcsicmp(strNodeName, PROPERTYOBJECTARRAY_TAG)) hr = MapPropertyObject (pNode, true, bIsModify); else if (0 == _wcsicmp(strNodeName, METHOD_TAG)) hr = MapMethod (pNode, bIsModify); else hr = WBEM_E_FAILED; // Parse error SysFreeString (strNodeName); } } pNode->Release (); } pNodeList->Release (); } } } SysFreeString(strClassName); pQualSet->Release (); } } return hr; } //*************************************************************************** // // HRESULT CXmlToWmi::MapInstance // // DESCRIPTION: // // Maps an XML <CLASS> into its WMI IWbemClassObject equivalent form // // PARAMETERS: // // // RETURN VALUES: // // //*************************************************************************** HRESULT CXmlToWmi::MapInstance ( bool bIsModify ) { HRESULT hr = WBEM_E_FAILED; if(m_pXml && m_pWmiObject) { IWbemQualifierSet *pQualSet = NULL; if (SUCCEEDED(m_pWmiObject->GetQualifierSet (&pQualSet))) { VARIANT_BOOL bHasChildNodes; if (SUCCEEDED(m_pXml->hasChildNodes (&bHasChildNodes)) && (VARIANT_TRUE == bHasChildNodes)) { IXMLDOMNodeList *pNodeList = NULL; if (SUCCEEDED(m_pXml->get_childNodes (&pNodeList))) { IXMLDOMNode *pNode = NULL; hr = WBEM_S_NO_ERROR; while (SUCCEEDED(hr) && SUCCEEDED(pNodeList->nextNode (&pNode)) &&pNode) { // Get the name of the element (QUALIFIER, PROPERTY, METHOD) BSTR strNodeName = NULL; if (SUCCEEDED(pNode->get_nodeName (&strNodeName))) { // Get the Name of the property/method/qualifier // We dont need to map system properties that begin with "__" bool bMap = false; BSTR strName = NULL; if(SUCCEEDED(hr = GetBstrAttribute(pNode, NAME_ATTRIBUTE, &strName))) { // See if it is one of the System Properties if(_wcsnicmp(strName, L"__", 2) != 0) bMap = true; SysFreeString(strName); } if(bMap) { if (0 == _wcsicmp(strNodeName, QUALIFIER_TAG)) hr = MapQualifier (pNode, pQualSet, true); if (0 == _wcsicmp(strNodeName, PROPERTY_TAG)) hr = MapProperty (pNode, false, bIsModify, true); else if (0 == _wcsicmp(strNodeName, PROPERTYARRAY_TAG)) hr = MapProperty (pNode, true, bIsModify, true); else if (0 == _wcsicmp(strNodeName, PROPERTYREFERENCE_TAG)) hr = MapPropertyReference (pNode, false, bIsModify, true); else if (0 == _wcsicmp(strNodeName, PROPERTYREFARRAY_TAG)) hr = MapPropertyReference (pNode, true, bIsModify, true); else if (0 == _wcsicmp(strNodeName, PROPERTYOBJECT_TAG)) hr = MapPropertyObject (pNode, false, bIsModify, true); else if (0 == _wcsicmp(strNodeName, PROPERTYOBJECTARRAY_TAG)) hr = MapPropertyObject (pNode, true, bIsModify, true); else hr = WBEM_E_FAILED; // Parse error } SysFreeString (strNodeName); } pNode->Release (); } pNodeList->Release (); } } pQualSet->Release (); } } return hr; } //*************************************************************************** // // HRESULT CXmlToWmi::MapContextObject // // DESCRIPTION: // // Maps an XML <INSTANCE> into a IWbemContext object // // PARAMETERS: // // // RETURN VALUES: // // //*************************************************************************** HRESULT CXmlToWmi::MapContextObject (IXMLDOMNode *pContextNode, IWbemContext **ppContext) { HRESULT hr = WBEM_E_FAILED; *ppContext = NULL; // Create an IWbemContext object using the information in the INSTANCE element if(SUCCEEDED(hr = CoCreateInstance(CLSID_WbemContext, 0, CLSCTX_INPROC_SERVER, IID_IWbemContext, (LPVOID *) ppContext))) { if(pContextNode) { // Go through the children of the INSTANCE node //************************************************** VARIANT_BOOL bHasChildNodes; if (SUCCEEDED(pContextNode->hasChildNodes (&bHasChildNodes)) && (VARIANT_TRUE == bHasChildNodes)) { IXMLDOMNodeList *pNodeList = NULL; if (SUCCEEDED(pContextNode->get_childNodes (&pNodeList))) { IXMLDOMNode *pNode = NULL; hr = WBEM_S_NO_ERROR; while (SUCCEEDED(hr) && SUCCEEDED(pNodeList->nextNode (&pNode)) &&pNode) { BSTR strNodeName = NULL; if (SUCCEEDED(pNode->get_nodeName (&strNodeName))) { if (0 == _wcsicmp(strNodeName, CONTEXTPROPERTY_TAG)) hr = MapContextProperty (pNode, *ppContext); else if (0 == _wcsicmp(strNodeName, CONTEXTPROPERTYARRAY_TAG)) hr = MapContextPropertyArray (pNode, *ppContext); /* RAJESHR These need to be mapped too !! else if (0 == _wcsicmp(strNodeName, CONTEXTPROPERTYOBJECT_TAG)) hr = MapContextPropertyObject (pNode, *ppContext); else if (0 == _wcsicmp(strNodeName, CONTEXTPROPERTYOBJECTARRAY_TAG)) hr = MapContextPropertyObjectArray (pNode, *ppContext); */ else hr = WBEM_E_FAILED; // Parse error SysFreeString (strNodeName); } pNode->Release (); } pNodeList->Release (); } } } } // Release the context object if the whole function call wasnt successful if(!SUCCEEDED(hr) && *ppContext) { (*ppContext)->Release(); *ppContext = NULL; } return hr; } HRESULT CXmlToWmi::MapQualifier ( IXMLDOMNode *pNode, IWbemQualifierSet *pQualSet, bool bInstance ) { HRESULT hr = S_OK; BSTR strName = NULL; BSTR strType = NULL; BSTR strOverridable = NULL; BSTR strToSubclass = NULL; BSTR strToInstance = NULL; BSTR strAmended = NULL; // Get the attributes we need for the mapping if(SUCCEEDED(hr)) { if(SUCCEEDED(hr = GetBstrAttribute (pNode, NAME_ATTRIBUTE, &strName))) { if(strName && bInstance) { // Dont map certain qualifiers for instances if(_wcsicmp(strName, L"CIMTYPE") == 0 || _wcsicmp(strName, L"KEY") == 0 ) { SysFreeString(strName); return S_OK; } } } } if(SUCCEEDED(hr)) hr = GetBstrAttribute (pNode, TYPE_ATTRIBUTE, &strType); if(SUCCEEDED(hr)) GetBstrAttribute (pNode, OVERRIDABLE_ATTRIBUTE, &strOverridable); if(SUCCEEDED(hr)) GetBstrAttribute (pNode, TOSUBCLASS_ATTRIBUTE, &strToSubclass); if(SUCCEEDED(hr)) GetBstrAttribute (pNode, TOINSTANCE_ATTRIBUTE, &strToInstance); if(SUCCEEDED(hr)) GetBstrAttribute (pNode, AMENDED_ATTRIBUTE, &strAmended); // Build up the flavor long flavor = 0; if(SUCCEEDED(hr)) { if (!strOverridable || (0 == _wcsicmp (strOverridable, L"true"))) flavor |= WBEM_FLAVOR_OVERRIDABLE; else if (0 == _wcsicmp (strOverridable, L"false")) flavor |= WBEM_FLAVOR_NOT_OVERRIDABLE; else hr = WBEM_E_FAILED; } if (SUCCEEDED(hr)) { if (!strToSubclass || (0 == _wcsicmp (strToSubclass, L"true"))) flavor |= WBEM_FLAVOR_FLAG_PROPAGATE_TO_DERIVED_CLASS; else if (0 != _wcsicmp (strToSubclass, L"false")) hr = WBEM_E_FAILED; } if (SUCCEEDED(hr)) { if (strToInstance && (0 == _wcsicmp (strToInstance, L"true"))) flavor |= WBEM_FLAVOR_FLAG_PROPAGATE_TO_INSTANCE; else if (strToInstance && (0 != _wcsicmp (strToInstance, L"false"))) hr = WBEM_E_FAILED; } if (SUCCEEDED(hr)) { if (strAmended && (0 == _wcsicmp (strAmended, L"true"))) flavor |= WBEM_FLAVOR_AMENDED; else if (strAmended && (0 != _wcsicmp (strAmended, L"false"))) hr = WBEM_E_FAILED; } // Map the Qualifier type CIMTYPE cimtype = CIM_ILLEGAL; if (CIM_ILLEGAL == (cimtype = CimtypeFromString (strType))) hr = WBEM_E_FAILED; // Map the Qualifier value VARIANT value; VariantInit (&value); if (SUCCEEDED (hr)) { IXMLDOMNodeList *pNodeList = NULL; long length = 0; if (SUCCEEDED(hr = pNode->get_childNodes (&pNodeList))) { if (SUCCEEDED(hr = pNodeList->get_length (&length)) && (1 == length)) { // Get the first node IXMLDOMNode *pValueNode = NULL; if (SUCCEEDED(hr = pNodeList->nextNode (&pValueNode)) && pValueNode) { // Get its name BSTR strNodeName = NULL; if(SUCCEEDED(hr = pValueNode->get_nodeName(&strNodeName))) { if (0 == _wcsicmp(strNodeName, VALUE_TAG)) { BSTR bsValue = NULL; if(SUCCEEDED(hr = pValueNode->get_text(&bsValue))) { hr = MapStringValue (bsValue, value, cimtype); SysFreeString (bsValue); } } else if (0 == _wcsicmp(strNodeName, VALUEARRAY_TAG)) { hr = MapStringArrayValue (pValueNode, value, cimtype); } SysFreeString (strNodeName); } pValueNode->Release (); } } pNodeList->Release (); } } // Put it all together if (SUCCEEDED (hr)) hr = pQualSet->Put (strName, &value, flavor); if (strName) SysFreeString (strName); if (strType) SysFreeString (strType); if (strOverridable) SysFreeString (strOverridable); if (strToSubclass) SysFreeString (strToSubclass); if (strToInstance) SysFreeString (strToInstance); if (strAmended) SysFreeString (strAmended); VariantClear (&value); return hr; } HRESULT CXmlToWmi::MapProperty ( IXMLDOMNode *pProperty, bool bIsArray, bool bIsModify, bool bIsInstance ) { HRESULT hr = S_OK; BSTR strName = NULL; BSTR strType = NULL; BSTR strArraySize = NULL; // Get the attributes we need for the mapping if(SUCCEEDED(hr)) hr = GetBstrAttribute (pProperty, NAME_ATTRIBUTE, &strName); if(SUCCEEDED(hr)) hr = GetBstrAttribute (pProperty, TYPE_ATTRIBUTE, &strType); // This is an optional attribute - hence we dont need to check for success if (SUCCEEDED(hr) && (bIsArray)) GetBstrAttribute (pProperty, ARRAYSIZE_ATTRIBUTE, &strArraySize); if (SUCCEEDED(hr) && pProperty && strName && strType) { // Map the Property type CIMTYPE cimtype = CIM_ILLEGAL; if (CIM_ILLEGAL == (cimtype = CimtypeFromString (strType))) hr = WBEM_E_FAILED; else if (bIsArray) cimtype |= CIM_FLAG_ARRAY; // Does this property exist already? If we're doing a modify it had better! hr = m_pWmiObject->Get(strName, 0, NULL, NULL, NULL); if (!bIsModify || SUCCEEDED(hr)) { // If we didn't find the property, put a provisional version // in so we can get the qualifier set if (SUCCEEDED(hr) || SUCCEEDED(hr = m_pWmiObject->Put(strName, 0, NULL, cimtype))) { IWbemQualifierSet *pQualSet = NULL; VARIANT value; VariantInit (&value); if (SUCCEEDED(hr = m_pWmiObject->GetPropertyQualifierSet (strName, &pQualSet))) { // If we have been given an ARRAYSIZE value then set this // as qualifiers of the property if (strArraySize) hr = SetArraySize (pQualSet, strArraySize); if (SUCCEEDED(hr)) { // The content of this element should be 0 or // more QUALIFIER elements followed by an optional VALUE // element. VARIANT_BOOL bHasChildNodes; if (SUCCEEDED(pProperty->hasChildNodes (&bHasChildNodes)) && (VARIANT_TRUE == bHasChildNodes)) { IXMLDOMNodeList *pNodeList = NULL; // We can be in one of 3 states whilst iterating // this list - parsing qualifiers or parsing the value // or value array enum { parsingQualifiers, parsingValue, parsingValueArray, } parseState = parsingQualifiers; if (SUCCEEDED(pProperty->get_childNodes (&pNodeList))) { IXMLDOMNode *pNode = NULL; while (SUCCEEDED(hr) && SUCCEEDED(pNodeList->nextNode (&pNode)) &&pNode) { BSTR strNodeName = NULL; if (SUCCEEDED(pNode->get_nodeName (&strNodeName))) { if (parsingQualifiers == parseState) { if (0 == _wcsicmp(strNodeName, QUALIFIER_TAG)) hr = MapQualifier (pNode, pQualSet, bIsInstance); else parseState = (bIsArray) ? parsingValueArray : parsingValue; } if (parsingValue == parseState) { if (0 == _wcsicmp(strNodeName, VALUE_TAG)) { BSTR bsValue = NULL; if(SUCCEEDED(hr = pNode->get_text(&bsValue))) { hr = MapStringValue (bsValue, value, cimtype); SysFreeString (bsValue); } } else hr = WBEM_E_FAILED; // Parse error } if (parsingValueArray == parseState) { if (0 == _wcsicmp(strNodeName, VALUEARRAY_TAG)) { hr = MapStringArrayValue (pNode, value, cimtype); } else hr = WBEM_E_FAILED; } SysFreeString (strNodeName); } pNode->Release (); } pNodeList->Release (); } } } pQualSet->Release (); } // Put it all together - only do this if we have a real value if (SUCCEEDED (hr) && (VT_EMPTY != value.vt)) hr = m_pWmiObject->Put (strName, 0, &value, cimtype); VariantClear (&value); } } } if (strName) SysFreeString (strName); if (strType) SysFreeString (strType); if (strArraySize) SysFreeString (strArraySize); return hr; } HRESULT CXmlToWmi::MapPropertyReference ( IXMLDOMNode *pProperty, bool bIsArray, bool bIsModify, bool bIsInstance ) { HRESULT hr = S_OK; if (pProperty) { BSTR strName = NULL; BSTR strReferenceClass = NULL; BSTR strArraySize = NULL; CIMTYPE cimtype = CIM_REFERENCE; if(bIsArray) cimtype |= CIM_FLAG_ARRAY; // Get the attributes we need for the mapping if(SUCCEEDED(hr)) hr = GetBstrAttribute (pProperty, NAME_ATTRIBUTE, &strName); if(SUCCEEDED(hr)) hr = GetBstrAttribute (pProperty, REFERENCECLASS_ATTRIBUTE, &strReferenceClass); // This is an optional attribute - hence we dont need to check for success if (SUCCEEDED(hr) && (bIsArray)) GetBstrAttribute (pProperty, ARRAYSIZE_ATTRIBUTE, &strArraySize); if (pProperty && strName) { // Does this property exist already? If we're doing a modify it had better! hr = m_pWmiObject->Get(strName, 0, NULL, NULL, NULL); if (!bIsModify || SUCCEEDED(hr)) { // If we didn't find the property, put a provisional version // in so we can get the qualifier set if (SUCCEEDED(hr) || SUCCEEDED(hr = m_pWmiObject->Put(strName, 0, NULL, cimtype))) { IWbemQualifierSet *pQualSet = NULL; VARIANT value; VariantInit (&value); if (SUCCEEDED(hr = m_pWmiObject->GetPropertyQualifierSet (strName, &pQualSet))) { // If we have been given an ARRAYSIZE value then set this // as qualifiers of the property if (strArraySize) hr = SetArraySize (pQualSet, strArraySize); // If we have been given a REFERENCECLASS value then set this // as qualifiers of the property if (strReferenceClass) hr = SetReferenceClass (pQualSet, strReferenceClass); if (SUCCEEDED(hr)) { // The content of this element should be 0 or // more QUALIFIER elements followed by an optional // VALUE.REFERENCE element. VARIANT_BOOL bHasChildNodes; if (SUCCEEDED(pProperty->hasChildNodes (&bHasChildNodes)) && (VARIANT_TRUE == bHasChildNodes)) { IXMLDOMNodeList *pNodeList = NULL; // We can be in one of 3 states whilst iterating // this list - parsing qualifiers or parsing the value enum { parsingQualifiers, parsingValue, parsingValueArray, } parseState = parsingQualifiers; if (SUCCEEDED(pProperty->get_childNodes (&pNodeList))) { IXMLDOMNode *pNode = NULL; while (SUCCEEDED(hr) && SUCCEEDED(pNodeList->nextNode (&pNode)) &&pNode) { BSTR strNodeName = NULL; if (SUCCEEDED(pNode->get_nodeName (&strNodeName))) { if (parsingQualifiers == parseState) { if (0 == _wcsicmp(strNodeName, QUALIFIER_TAG)) hr = MapQualifier (pNode, pQualSet, bIsInstance); else parseState = (bIsArray)? parsingValueArray : parsingValue; } if (parsingValue == parseState) { if (0 == _wcsicmp(strNodeName, VALUEREFERENCE_TAG)) { hr = MapReferenceValue (pNode, value); } else hr = WBEM_E_FAILED; // Parse error } if (parsingValueArray == parseState) { if (0 == _wcsicmp(strNodeName, VALUEREFARRAY_TAG)) { hr = MapReferenceArrayValue (pNode, value); } else hr = WBEM_E_FAILED; // Parse error } SysFreeString (strNodeName); } pNode->Release (); } pNodeList->Release (); } } } pQualSet->Release (); } // Put it all together - only do this if we have a real value if (SUCCEEDED (hr) && (VT_EMPTY != value.vt)) hr = m_pWmiObject->Put (strName, 0, &value, cimtype); VariantClear (&value); } } } SysFreeString (strName); SysFreeString (strReferenceClass); SysFreeString (strArraySize); } return hr; } HRESULT CXmlToWmi::MapPropertyObject ( IXMLDOMNode *pProperty, bool bIsArray, bool bIsModify, bool bIsInstance ) { HRESULT hr = S_OK; if (pProperty) { BSTR strName = NULL; BSTR strReferenceClass = NULL; BSTR strArraySize = NULL; CIMTYPE cimtype = CIM_REFERENCE; if(bIsArray) cimtype |= CIM_FLAG_ARRAY; // Get the attributes we need for the mapping if(SUCCEEDED(hr)) hr = GetBstrAttribute (pProperty, NAME_ATTRIBUTE, &strName); if(SUCCEEDED(hr)) hr = GetBstrAttribute (pProperty, REFERENCECLASS_ATTRIBUTE, &strReferenceClass); // This is an optional attribute - hence we dont need to check for success if (SUCCEEDED(hr) && (bIsArray)) GetBstrAttribute (pProperty, ARRAYSIZE_ATTRIBUTE, &strArraySize); if (pProperty && strName) { // Does this property exist already? If we're doing a modify it had better! hr = m_pWmiObject->Get(strName, 0, NULL, NULL, NULL); if (!bIsModify || SUCCEEDED(hr)) { // If we didn't find the property, put a provisional version // in so we can get the qualifier set if (SUCCEEDED(hr) || SUCCEEDED(hr = m_pWmiObject->Put(strName, 0, NULL, cimtype))) { IWbemQualifierSet *pQualSet = NULL; VARIANT value; VariantInit (&value); if (SUCCEEDED(hr = m_pWmiObject->GetPropertyQualifierSet (strName, &pQualSet))) { // If we have been given an ARRAYSIZE value then set this // as qualifiers of the property if (strArraySize) hr = SetArraySize (pQualSet, strArraySize); // If we have been given a REFERENCECLASS value then set this // as qualifiers of the property if (strReferenceClass) hr = SetObjectClass (pQualSet, strReferenceClass); if (SUCCEEDED(hr)) { // The content of this element should be 0 or // more QUALIFIER elements followed by an optional // VALUE.OBJECT element. VARIANT_BOOL bHasChildNodes; if (SUCCEEDED(pProperty->hasChildNodes (&bHasChildNodes)) && (VARIANT_TRUE == bHasChildNodes)) { IXMLDOMNodeList *pNodeList = NULL; // We can be in one of 3 states whilst iterating // this list - parsing qualifiers or parsing the value enum { parsingQualifiers, parsingValue, parsingValueArray, } parseState = parsingQualifiers; if (SUCCEEDED(pProperty->get_childNodes (&pNodeList))) { IXMLDOMNode *pNode = NULL; while (SUCCEEDED(hr) && SUCCEEDED(pNodeList->nextNode (&pNode)) &&pNode) { BSTR strNodeName = NULL; if (SUCCEEDED(pNode->get_nodeName (&strNodeName))) { if (parsingQualifiers == parseState) { if (0 == _wcsicmp(strNodeName, QUALIFIER_TAG)) hr = MapQualifier (pNode, pQualSet, bIsInstance); else parseState = (bIsArray)? parsingValueArray : parsingValue; } if (parsingValue == parseState) { if (0 == _wcsicmp(strNodeName, VALUEOBJECT_TAG)) { hr = MapObjectValue (pNode, value); } else hr = WBEM_E_FAILED; // Parse error } if (parsingValueArray == parseState) { if (0 == _wcsicmp(strNodeName, VALUEOBJECTARRAY_TAG)) { hr = MapObjectArrayValue (pNode, value); } else hr = WBEM_E_FAILED; // Parse error } SysFreeString (strNodeName); } pNode->Release (); } pNodeList->Release (); } } } pQualSet->Release (); } // Put it all together - only do this if we have a real value if (SUCCEEDED (hr) && (VT_EMPTY != value.vt)) hr = m_pWmiObject->Put (strName, 0, &value, cimtype); VariantClear (&value); } } } SysFreeString (strName); SysFreeString (strReferenceClass); SysFreeString (strArraySize); } return hr; } HRESULT CXmlToWmi::MapMethod ( IXMLDOMNode *pMethod, bool bIsModify ) { HRESULT hr = WBEM_E_FAILED; if (pMethod) { BSTR strName = NULL; BSTR strType = NULL; // Get the attributes we need for the mapping GetBstrAttribute (pMethod, NAME_ATTRIBUTE, &strName); GetBstrAttribute (pMethod, TYPE_ATTRIBUTE, &strType); if (pMethod && strName) { // Does this method exist already? If we're doing a modify it had better! hr = m_pWmiObject->GetMethod(strName, 0, NULL, NULL); if (!bIsModify || SUCCEEDED(hr)) { // If we didn't find the method, put a provisional version // in so we can get the qualifier set if (SUCCEEDED(hr) || SUCCEEDED(hr = m_pWmiObject->PutMethod(strName, 0, NULL, NULL))) { IWbemQualifierSet *pQualSet = NULL; IWbemClassObject *pInParameters = NULL; IWbemClassObject *pOutParameters = NULL; if (SUCCEEDED(hr = m_pWmiObject->GetMethodQualifierSet (strName, &pQualSet))) { // If we have a return value, set that if (strType && (0 < wcslen (strType))) { CIMTYPE cimtype = CIM_ILLEGAL; if (CIM_ILLEGAL == (cimtype = CimtypeFromString (strType))) hr = WBEM_E_FAILED; else if (SUCCEEDED(hr = m_pServices->GetObject (L"__PARAMETERS", 0, NULL, &pOutParameters, NULL))) hr = pOutParameters->Put (L"ReturnValue", 0, NULL, cimtype); } // The content of this element should be 0 or // more QUALIFIER elements followed by 0 or more // PARAMETER.* elements. VARIANT_BOOL bHasChildNodes; if (SUCCEEDED(pMethod->hasChildNodes (&bHasChildNodes)) && (VARIANT_TRUE == bHasChildNodes)) { IXMLDOMNodeList *pNodeList = NULL; // We can be in one of 3 states whilst iterating // this list - parsing qualifiers or parsing the value enum { parsingQualifiers, parsingParameters } parseState = parsingQualifiers; if (SUCCEEDED(pMethod->get_childNodes (&pNodeList))) { IXMLDOMNode *pNode = NULL; ULONG paramId = 0; while (SUCCEEDED(hr) && SUCCEEDED(pNodeList->nextNode (&pNode)) &&pNode) { BSTR strNodeName = NULL; if (SUCCEEDED(pNode->get_nodeName (&strNodeName))) { if (parsingQualifiers == parseState) { if (0 == _wcsicmp(strNodeName, QUALIFIER_TAG)) hr = MapQualifier (pNode, pQualSet); else parseState = parsingParameters; } if (parsingParameters == parseState) { if (0 == _wcsicmp(strNodeName, PARAMETER_TAG)) { hr = MapParameter (pNode, &pInParameters, &pOutParameters, m_pServices, paramId); paramId++; } else if (0 == _wcsicmp(strNodeName, PARAMETERREFERENCE_TAG)) { hr = MapReferenceParameter (pNode, &pInParameters, &pOutParameters, m_pServices, paramId); paramId++; } else if (0 == _wcsicmp(strNodeName, PARAMETERARRAY_TAG)) { hr = MapParameter (pNode, &pInParameters, &pOutParameters, m_pServices, paramId, true); paramId++; } else if (0 == _wcsicmp(strNodeName, PARAMETERREFARRAY_TAG)) { hr = MapReferenceParameter (pNode, &pInParameters, &pOutParameters, m_pServices, paramId, true); paramId++; } else hr = WBEM_E_FAILED; // Parse error } SysFreeString (strNodeName); } pNode->Release (); } pNodeList->Release (); } } pQualSet->Release (); } // Put it all together if (SUCCEEDED (hr)) hr = m_pWmiObject->PutMethod (strName, 0, pInParameters, pOutParameters); if (pInParameters) pInParameters->Release (); if (pOutParameters) pOutParameters->Release (); } } } if (strName) SysFreeString (strName); if (strType) SysFreeString (strType); } return hr; } HRESULT CXmlToWmi::MapParameter ( IXMLDOMNode *pParameter, IWbemClassObject **ppInParameters, IWbemClassObject **ppOutParameters, IWbemServices *pService, ULONG paramId, bool bIsArray ) { HRESULT hr = WBEM_E_FAILED; bool bIsInParameter = false; bool bIsOutParameter = false; BSTR bsName = NULL; CIMTYPE cimtype = CIM_ILLEGAL; long iArraySize = 0; if (DetermineParameterCharacteristics (pParameter, bIsArray, bIsInParameter, bIsOutParameter, bsName, cimtype, iArraySize)) { if (bIsInParameter) { if (!(*ppInParameters)) pService->GetObject (L"__PARAMETERS", 0, NULL, ppInParameters, NULL); if (*ppInParameters) { if (SUCCEEDED(hr = (*ppInParameters)->Put (bsName, 0, NULL, cimtype))) { // Now do the qualifiers IWbemQualifierSet *pQualSet = NULL; if (SUCCEEDED(hr = (*ppInParameters)->GetPropertyQualifierSet (bsName, &pQualSet))) { hr = MapParameterQualifiers (pParameter, pQualSet, paramId, bIsArray, iArraySize, true); pQualSet->Release (); } } } } if (bIsOutParameter) { if (!(*ppOutParameters)) pService->GetObject (L"__PARAMETERS", 0, NULL, ppOutParameters, NULL); if (*ppOutParameters) { if (SUCCEEDED(hr = (*ppOutParameters)->Put (bsName, 0, NULL, cimtype))) { // Now do the qualifiers IWbemQualifierSet *pQualSet = NULL; if (SUCCEEDED(hr = (*ppOutParameters)->GetPropertyQualifierSet (bsName, &pQualSet))) { hr = MapParameterQualifiers (pParameter, pQualSet, paramId, bIsArray, iArraySize); pQualSet->Release (); } } } } SysFreeString (bsName); } return hr; } bool CXmlToWmi::DetermineParameterCharacteristics ( IXMLDOMNode *pParameter, bool bIsArray, bool &bIsInParameter, bool &bIsOutParameter, BSTR &bsName, CIMTYPE &cimtype, long &iArraySize, bool bIsReference, BSTR *pbsReferenceClass) { bool result = false; bIsInParameter = false; bIsOutParameter = false; // Get name GetBstrAttribute (pParameter, NAME_ATTRIBUTE, &bsName); if (bsName) { if (bIsArray) { // Get the arraysize (if any) BSTR bsArraySize = NULL; GetBstrAttribute (pParameter, ARRAYSIZE_ATTRIBUTE, &bsArraySize); if (bsArraySize) { iArraySize = wcstol (bsArraySize, NULL, 0); SysFreeString (bsArraySize); } } // Now get the cimtype if (bIsReference) { cimtype = CIM_REFERENCE; if (pbsReferenceClass) GetBstrAttribute (pParameter, REFERENCECLASS_ATTRIBUTE, pbsReferenceClass); } else { BSTR bsCimtype = NULL; GetBstrAttribute (pParameter, TYPE_ATTRIBUTE, &bsCimtype); cimtype = CimtypeFromString (bsCimtype); if (bsCimtype) SysFreeString (bsCimtype); } if (CIM_ILLEGAL != cimtype) { if (bIsArray) cimtype |= CIM_FLAG_ARRAY; result = true; // Now find out if the method is an in or out // (or both) parameter - need to go through // qualifier list IXMLDOMNodeList *pNodeList = NULL; if (SUCCEEDED(pParameter->get_childNodes (&pNodeList))) { IXMLDOMNode *pNode = NULL; HRESULT hr = S_OK; while (SUCCEEDED(hr) && SUCCEEDED(pNodeList->nextNode (&pNode)) &&pNode) { BSTR strNodeName = NULL; if (SUCCEEDED(pNode->get_nodeName (&strNodeName))) { if (0 == _wcsicmp(strNodeName, QUALIFIER_TAG)) { BSTR bsName = NULL; GetBstrAttribute (pNode, NAME_ATTRIBUTE, &bsName); if (bsName) { bool bCandidate = false; bool bsIn = true; if (0 == _wcsicmp (bsName, L"IN")) bCandidate = true; else if (0 == _wcsicmp (bsName, L"OUT")) { bCandidate = true; bsIn = false; } if (bCandidate) { BSTR bsType = NULL; GetBstrAttribute (pNode, TYPE_ATTRIBUTE, &bsType); if (bsType && (0 == _wcsicmp (bsType, L"boolean"))) { BSTR bsValue = NULL; if (SUCCEEDED(pNode->get_text(&bsValue)) && bsValue && (0 == _wcsicmp (bsValue, L"TRUE"))) { if (bsIn) bIsInParameter = true; else bIsOutParameter = true; } } SysFreeString (bsType); } SysFreeString (bsName); } } SysFreeString (strNodeName); } pNode->Release (); } pNodeList->Release (); } } } if (!result) { if (bsName) { SysFreeString (bsName); bsName = NULL; } } return result; } HRESULT CXmlToWmi::MapParameterQualifiers ( IXMLDOMNode *pParameter, IWbemQualifierSet *pQualSet, ULONG paramId, bool bIsArray, long iArraySize, bool bIsInParameter ) { HRESULT hr = S_OK; IXMLDOMNodeList *pNodeList = NULL; if (SUCCEEDED(pParameter->get_childNodes (&pNodeList))) { IXMLDOMNode *pNode = NULL; while (SUCCEEDED(hr) && SUCCEEDED(pNodeList->nextNode (&pNode)) &&pNode) { BSTR strNodeName = NULL; if (SUCCEEDED(pNode->get_nodeName (&strNodeName))) { if (0 == _wcsicmp(strNodeName, QUALIFIER_TAG)) { // We must only add the IN qualifier to an In parameter, // and the OUT parameter to an Out parameter BSTR bsName = NULL; GetBstrAttribute (pNode, NAME_ATTRIBUTE, &bsName); if (bsName) { if (0 == _wcsicmp (bsName, L"IN")) { if (bIsInParameter) hr = MapQualifier (pNode, pQualSet); } else if (0 == _wcsicmp (bsName, L"OUT")) { if (!bIsInParameter) hr = MapQualifier (pNode, pQualSet); } else hr = MapQualifier (pNode, pQualSet); SysFreeString (bsName); } } else hr = WBEM_E_FAILED; SysFreeString (strNodeName); } pNode->Release (); } if (SUCCEEDED(hr)) { long flavor = WBEM_FLAVOR_NOT_OVERRIDABLE | WBEM_FLAVOR_FLAG_PROPAGATE_TO_DERIVED_CLASS; // Add in the parameter id VARIANT var; VariantInit (&var); var.vt = VT_I4; var.lVal = paramId; hr = pQualSet->Put (L"ID", &var, flavor); VariantClear (&var); if (SUCCEEDED(hr) && bIsArray && (0 < iArraySize)) { // Add in MIN and MAX qualifiers var.vt = VT_I4; var.lVal = iArraySize; if (SUCCEEDED(hr = pQualSet->Put (L"MAX", &var, flavor))) hr = pQualSet->Put (L"MIN", &var, flavor); } } pNodeList->Release (); } return hr; } HRESULT CXmlToWmi::MapReferenceParameter ( IXMLDOMNode *pParameter, IWbemClassObject **ppInParameters, IWbemClassObject **ppOutParameters, IWbemServices *pService, ULONG paramId, bool bIsArray ) { HRESULT hr = WBEM_E_FAILED; bool bIsInParameter = false; bool bIsOutParameter = false; BSTR bsName = NULL; BSTR bsReferenceClass = NULL; long iArraySize = 0; CIMTYPE cimtype = CIM_ILLEGAL; if (DetermineParameterCharacteristics (pParameter, bIsArray, bIsInParameter, bIsOutParameter, bsName, cimtype, iArraySize, true, &bsReferenceClass)) { if (bIsInParameter) { if (!(*ppInParameters)) pService->GetObject (L"__PARAMETERS", 0, NULL, ppInParameters, NULL); if (*ppInParameters) { if (SUCCEEDED(hr = (*ppInParameters)->Put (bsName, 0, NULL, cimtype))) { // Now do the qualifiers IWbemQualifierSet *pQualSet = NULL; if (SUCCEEDED(hr = (*ppInParameters)->GetPropertyQualifierSet (bsName, &pQualSet))) { hr = MapParameterQualifiers (pParameter, pQualSet, paramId, bIsArray, iArraySize, true); // If a strong reference, add it now if (bsReferenceClass) SetReferenceClass (pQualSet, bsReferenceClass); pQualSet->Release (); } } } } if (bIsOutParameter) { if (!(*ppOutParameters)) pService->GetObject (L"__PARAMETERS", 0, NULL, ppOutParameters, NULL); if (*ppOutParameters) { if (SUCCEEDED(hr = (*ppOutParameters)->Put (bsName, 0, NULL, cimtype))) { // Now do the qualifiers IWbemQualifierSet *pQualSet = NULL; if (SUCCEEDED(hr = (*ppOutParameters)->GetPropertyQualifierSet (bsName, &pQualSet))) { hr = MapParameterQualifiers (pParameter, pQualSet, paramId, bIsArray, iArraySize); // If a strong reference, add it now if (bsReferenceClass) SetReferenceClass (pQualSet, bsReferenceClass); pQualSet->Release (); } } } } SysFreeString (bsName); } if (bsReferenceClass) SysFreeString (bsReferenceClass); return hr; } //*************************************************************************** // // HRESULT CXmlToWmi::MapPropertyValue // // DESCRIPTION: // // Maps an XML property value into its WMI VARIANT equivalent form // // PARAMETERS: // // curValue Placeholder for new value (set on return) // cimtype CIMTYPE of property (needed for mapping) // // RETURN VALUES: // // //*************************************************************************** HRESULT CXmlToWmi::MapPropertyValue ( VARIANT &curValue, CIMTYPE cimtype) { HRESULT hr = WBEM_E_FAILED; // Parse the XML body to extract the value - we // are expecting (VALUE|VALUE.ARRAY|VALUE.REFERENCE)? // Get its name BSTR strNodeName = NULL; if(m_pXml && SUCCEEDED(m_pXml->get_nodeName(&strNodeName))) { if (_wcsicmp(strNodeName, VALUE_TAG) == 0) { // RAJESHR - check only one node BSTR bsValue = NULL; m_pXml->get_text(&bsValue); hr = MapStringValue (bsValue, curValue, cimtype); SysFreeString (bsValue); } else if (_wcsicmp(strNodeName, VALUEARRAY_TAG) == 0) { hr = MapStringArrayValue (m_pXml, curValue, cimtype); } else if (_wcsicmp(strNodeName, VALUEREFERENCE_TAG) == 0) { if (CIM_REFERENCE == cimtype) hr = MapReferenceValue (m_pXml, curValue); else hr = WBEM_E_TYPE_MISMATCH; } SysFreeString (strNodeName); } else { // Assume value is NULL VariantClear (&curValue); curValue.vt = VT_NULL; hr = S_OK; } return hr; } //*************************************************************************** // // HRESULT CXmlToWmi::MapStringValue // // DESCRIPTION: // // Maps XML VALUE element content into its WMI VARIANT equivalent form // // PARAMETERS: // // bsValue the VALUE element content // curValue Placeholder for new value (set on return) // cimtype for mapping purposes // // RETURN VALUES: // // //*************************************************************************** HRESULT CXmlToWmi::MapStringValue (BSTR bsValue, VARIANT &curValue, CIMTYPE cimtype) { // RAJESHR First we need to remove any CDATA section from the string value // Even though the WMI implementation used CDATA (if necessary) only for CIM_STRING and CIM_DATETIME, // other implementations might use a CDATA to escape other values as well HRESULT hr = WBEM_E_TYPE_MISMATCH; // We're assuming it's not an array if (!(cimtype & CIM_FLAG_ARRAY)) { switch (cimtype) { // RAJESHR - more rigorous syntax checking case CIM_UINT8: { VariantClear (&curValue); curValue.vt = VT_UI1; curValue.bVal = (BYTE) wcstol (bsValue, NULL, 0); hr = S_OK; } break; case CIM_SINT8: case CIM_SINT16: { VariantClear (&curValue); curValue.vt = VT_I2; curValue.iVal = (short) wcstol (bsValue, NULL, 0); hr = S_OK; } break; case CIM_UINT16: case CIM_UINT32: case CIM_SINT32: { VariantClear (&curValue); curValue.vt = VT_I4; curValue.lVal = wcstol (bsValue, NULL, 0); hr = S_OK; } break; case CIM_REAL32: { VariantClear (&curValue); curValue.vt = VT_R4; curValue.fltVal = (float) wcstod (bsValue, NULL); hr = S_OK; } break; case CIM_REAL64: { VariantClear (&curValue); curValue.vt = VT_R8; curValue.dblVal = wcstod (bsValue, NULL); hr = S_OK; } break; case CIM_BOOLEAN: { VariantClear (&curValue); curValue.vt = VT_BOOL; curValue.boolVal = (0 == _wcsicmp (bsValue, L"TRUE")) ? VARIANT_TRUE : VARIANT_FALSE; hr = S_OK; } break; case CIM_CHAR16: { // 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 VariantClear (&curValue); curValue.vt = VT_I2; if(_wcsnicmp(bsValue, L"\\x", 2) == 0) // It is an escaped value swscanf (bsValue+2, L"%x", &(curValue.iVal)); else // It is a normal value swscanf (bsValue, L"%c", &(curValue.iVal)); hr = S_OK; } break; case CIM_STRING: case CIM_UINT64: case CIM_SINT64: case CIM_DATETIME: { VariantClear (&curValue); curValue.vt = VT_BSTR; curValue.bstrVal = SysAllocString (bsValue); hr = S_OK; } break; } } return hr; } //*************************************************************************** // // HRESULT CXmlToWmi::MapStringArrayValue // // DESCRIPTION: // // Maps XML VALUE.ARRAY element content into its WMI VARIANT equivalent form // // PARAMETERS: // // pValueNode the VALUE.ARRAY node // curValue Placeholder for new value (set on return) // cimtype for mapping purposes // // RETURN VALUES: // // //*************************************************************************** HRESULT CXmlToWmi::MapStringArrayValue ( IXMLDOMNode *pValueNode, VARIANT &curValue, CIMTYPE cimtype ) { HRESULT hr = WBEM_E_TYPE_MISMATCH; // Build a safearray value from the node list IXMLDOMNodeList *pValueList = NULL; if (SUCCEEDED (pValueNode->get_childNodes (&pValueList))) { long length = 0; pValueList->get_length (&length); SAFEARRAYBOUND rgsabound [1]; rgsabound [0].lLbound = 0; rgsabound [0].cElements = length; VARTYPE vt = VTFromCIMType (cimtype & ~CIM_FLAG_ARRAY); SAFEARRAY *pArray = NULL; if(pArray = SafeArrayCreate (vt, 1, rgsabound)) { IXMLDOMNode *pValue = NULL; long ix = 0; bool error = false; while (!error && SUCCEEDED(pValueList->nextNode(&pValue)) && pValue) { BSTR strValName = NULL; if (SUCCEEDED(pValue->get_nodeName (&strValName))) { if (0 == _wcsicmp (strValName, VALUE_TAG)) { BSTR bsValue = NULL; pValue->get_text (&bsValue); if(FAILED(MapStringValueIntoArray (bsValue, pArray, &ix, vt, cimtype & ~CIM_FLAG_ARRAY))) error = true; SysFreeString (bsValue); ix++; } else { // unexpected element error = true; } SysFreeString (strValName); } pValue->Release (); pValue = NULL; } if (error) SafeArrayDestroy(pArray); else { curValue.vt = VT_ARRAY|vt; curValue.parray = pArray; hr = S_OK; } } else hr = E_OUTOFMEMORY; pValueList->Release(); } return hr; } //*************************************************************************** // // HRESULT CXmlToWmi::MapStringValueIntoArray // // DESCRIPTION: // // Maps XML VALUE.ARRAY/VALUE element content into its WMI VARIANT equivalent form // // PARAMETERS: // // bsValue the VALUE element content // pArray SAFEARRAY in which to map the value // ix index to map the value into // vt VARTYPE of the SAFEARRAY // cimtype for mapping purposes // // RETURN VALUES: // // //*************************************************************************** HRESULT CXmlToWmi::MapStringValueIntoArray ( BSTR bsValue, SAFEARRAY *pArray, long *ix, VARTYPE vt, CIMTYPE cimtype) { HRESULT hr = E_FAIL; switch (vt) { case VT_UI1: { BYTE bVal = (BYTE) wcstol (bsValue, NULL, 0); hr = SafeArrayPutElement (pArray, ix, &bVal); } break; case VT_I2: { short iVal; if (CIM_CHAR16 == cimtype) swscanf (bsValue, L"%c", &(iVal)); else iVal = (short) wcstol (bsValue, NULL, 0); hr = SafeArrayPutElement (pArray, ix, &iVal); } break; case VT_I4: { long lVal = wcstol (bsValue, NULL, 0); hr = SafeArrayPutElement (pArray, ix, &lVal); } break; case VT_R4: { float fltVal = (float) wcstod (bsValue, NULL); hr = SafeArrayPutElement (pArray, ix, &fltVal); } break; case VT_R8: { double dblVal = wcstod (bsValue, NULL); hr = SafeArrayPutElement (pArray, ix, &dblVal); } break; case VT_BOOL: { VARIANT_BOOL boolVal = (0 == _wcsicmp (bsValue, L"TRUE")) ? VARIANT_TRUE : VARIANT_FALSE; hr = SafeArrayPutElement (pArray, ix, &boolVal); } break; case VT_BSTR: hr = SafeArrayPutElement (pArray, ix, bsValue); break; } return hr; } //*************************************************************************** // // HRESULT CXmlToWmi::MapReferenceValue // // DESCRIPTION: // // Maps XML VALUE.REFERENCE element content into its WMI VARIANT equivalent form // // PARAMETERS: // // curValue Placeholder for new value (set on return) // cimtype for mapping purposes // // RETURN VALUES: // // //*************************************************************************** HRESULT CXmlToWmi::MapReferenceValue (IXMLDOMNode *pValue, VARIANT &curValue) { HRESULT hr = WBEM_E_FAILED; curValue.vt = VT_BSTR; if(SUCCEEDED(hr = ParseOneReferenceValue(pValue, &curValue.bstrVal))) { } return hr; } //*************************************************************************** // // HRESULT CXmlToWmi::MapReferenceArrayValue // // DESCRIPTION: // // Maps XML VALUE.REFARRAY element content into its WMI VARIANT equivalent form // // PARAMETERS: // // pValueNode the VALUE.REFARRAY node // curValue Placeholder for new value (set on return) // // RETURN VALUES: // // //*************************************************************************** HRESULT CXmlToWmi::MapReferenceArrayValue ( IXMLDOMNode *pValueNode, VARIANT &curValue ) { HRESULT hr = WBEM_E_TYPE_MISMATCH; // Build a safearray value from the node list underneath VALUE.REFARRAY // Each such node is a VALUE.REFERENCE IXMLDOMNodeList *pValueList = NULL; if (SUCCEEDED (pValueNode->get_childNodes (&pValueList))) { long length = 0; pValueList->get_length (&length); SAFEARRAYBOUND rgsabound [1]; rgsabound [0].lLbound = 0; rgsabound [0].cElements = length; VARTYPE vt = VTFromCIMType (CIM_REFERENCE & ~CIM_FLAG_ARRAY); SAFEARRAY *pArray = NULL; if(pArray = SafeArrayCreate (vt, 1, rgsabound)) { IXMLDOMNode *pValue = NULL; long ix = 0; bool error = false; while (!error && SUCCEEDED(pValueList->nextNode(&pValue)) && pValue) { BSTR strValName = NULL; if (SUCCEEDED(pValue->get_nodeName (&strValName))) { if (0 == _wcsicmp (strValName, VALUEREFERENCE_TAG)) { BSTR strNextValue = NULL; if(SUCCEEDED(ParseOneReferenceValue(pValue, &strNextValue))) { if(FAILED(SafeArrayPutElement (pArray, &ix, strNextValue))) error = true; SysFreeString(strNextValue); } ix++; } else { // unexpected element error = true; } SysFreeString (strValName); } pValue->Release (); pValue = NULL; } if (error) SafeArrayDestroy(pArray); else { curValue.vt = VT_ARRAY|vt; curValue.parray = pArray; hr = S_OK; } } else hr = E_OUTOFMEMORY; pValueList->Release(); } return hr; } //*************************************************************************** // // HRESULT CXmlToWmi::MapObjectValue // // DESCRIPTION: // // Maps XML VALUE.OBJECT element content into its WMI VARIANT equivalent form // // PARAMETERS: // // curValue Placeholder for new value (set on return) // cimtype for mapping purposes // // RETURN VALUES: // // //*************************************************************************** HRESULT CXmlToWmi::MapObjectValue (IXMLDOMNode *pValue, VARIANT &curValue) { HRESULT hr = WBEM_E_FAILED; curValue.vt = VT_UNKNOWN; if(SUCCEEDED(hr = MapOneObjectValue(pValue, &curValue.punkVal))) { } return hr; } HRESULT CXmlToWmi::MapOneObjectValue (IXMLDOMNode *pValueRef, IUnknown **ppunkValue) { HRESULT hr = E_FAIL; // Let's look at the child of the VALUE.OBJECT tag IXMLDOMNode *pChild = NULL; if (SUCCEEDED(pValueRef->get_firstChild (&pChild)) && pChild) { // Next node should be a CLASS or an INSTANCE element BSTR strNodeName = NULL; if(SUCCEEDED(pChild->get_nodeName(&strNodeName))) { // In this case, we need the superclass (if any) // to spawn a derived class if (_wcsicmp(strNodeName, CLASS_TAG) == 0) { // Should have a CLASS element - does it have a SUPERCLASS attribute? BSTR strSuperClass = NULL; GetBstrAttribute (pChild, SUPERCLASS_ATTRIBUTE, &strSuperClass); IWbemClassObject *pObject = NULL; if (WBEM_S_NO_ERROR == (hr = m_pServices->GetObject (strSuperClass, 0, NULL, &pObject, NULL))) { // Got the underlying class - now map the new value if (strSuperClass && (0 < wcslen (strSuperClass))) { IWbemClassObject *pSubClass = NULL; if (SUCCEEDED(hr = pObject->SpawnDerivedClass (0, &pSubClass))) { CXmlToWmi xmlToWmi; if(SUCCEEDED(hr = xmlToWmi.Initialize(pChild, m_pServices, pSubClass))) { if(SUCCEEDED(hr = xmlToWmi.MapClass ())) { *ppunkValue = pSubClass; pSubClass->AddRef(); } } pSubClass->Release (); } } else { CXmlToWmi xmlToWmi; if(SUCCEEDED(hr = xmlToWmi.Initialize(pChild, m_pServices, pObject))) { hr = xmlToWmi.MapClass (); } } pObject->Release (); } SysFreeString(strSuperClass); } else if (_wcsicmp(strNodeName, INSTANCE_TAG) == 0) { // In this case, we need the class object of the instance // to spawn an instance IWbemClassObject *pObject = NULL; // Should have a CLASSNAME attribute BSTR strClassName = NULL; GetBstrAttribute (pChild, CLASS_NAME_ATTRIBUTE, &strClassName); if (strClassName && (0 < wcslen (strClassName)) && WBEM_S_NO_ERROR == (hr = m_pServices->GetObject (strClassName, 0, NULL, &pObject, NULL))) { // Got the underlying class - now map the new value IWbemClassObject *pNewInstance = NULL; if (SUCCEEDED(hr = pObject->SpawnInstance (0, &pNewInstance))) { CXmlToWmi xmlToWmi; if(SUCCEEDED(hr = xmlToWmi.Initialize(pChild, m_pServices, pNewInstance))) { if (SUCCEEDED (hr = xmlToWmi.MapInstance ())) { *ppunkValue = pNewInstance; pNewInstance->AddRef(); } } pNewInstance->Release (); } pObject->Release (); } else hr = WBEM_E_FAILED; SysFreeString (strClassName); } SysFreeString(strNodeName); } pChild->Release(); } return hr; } //*************************************************************************** // // HRESULT CXmlToWmi::MapObjectArrayValue // // DESCRIPTION: // // Maps XML VALUE.OBJECTARRAY element content into its WMI VARIANT equivalent form // // PARAMETERS: // // pValueNode the VALUE.OBJECTARRAY node // curValue Placeholder for new value (set on return) // // RETURN VALUES: // // //*************************************************************************** HRESULT CXmlToWmi::MapObjectArrayValue ( IXMLDOMNode *pValueNode, VARIANT &curValue) { HRESULT hr = WBEM_E_TYPE_MISMATCH; // Build a safearray value from the node list underneath VALUE.OBJECTARRAY // Each such node is a VALUE.OBJECT IXMLDOMNodeList *pValueList = NULL; if (SUCCEEDED (pValueNode->get_childNodes (&pValueList))) { long length = 0; pValueList->get_length (&length); SAFEARRAYBOUND rgsabound [1]; rgsabound [0].lLbound = 0; rgsabound [0].cElements = length; VARTYPE vt = VTFromCIMType (CIM_OBJECT & ~CIM_FLAG_ARRAY); SAFEARRAY *pArray = NULL; if(pArray = SafeArrayCreate (vt, 1, rgsabound)) { IXMLDOMNode *pValue = NULL; long ix = 0; bool error = false; while (!error && SUCCEEDED(pValueList->nextNode(&pValue)) && pValue) { BSTR strValName = NULL; if (SUCCEEDED(pValue->get_nodeName (&strValName))) { if (0 == _wcsicmp (strValName, VALUEOBJECT_TAG)) { IUnknown *pNextValue = NULL; if(SUCCEEDED(MapOneObjectValue(pValue, &pNextValue))) { if(FAILED(SafeArrayPutElement (pArray, &ix, pNextValue))) error = true; pNextValue->Release();; } ix++; } else { // unexpected element error = true; } SysFreeString (strValName); } pValue->Release (); pValue = NULL; } if (error) SafeArrayDestroy(pArray); else { curValue.vt = VT_ARRAY|vt; curValue.parray = pArray; hr = S_OK; } } else hr = E_OUTOFMEMORY; pValueList->Release(); } return hr; } //*************************************************************************** // // HRESULT CXmlToWmi::VTFromCIMType // // DESCRIPTION: // // Utility function to map CIMTYPE to its VARTYPE equivalent // // PARAMETERS: // // cimtype the CIMTYPE to be mapped // // RETURN VALUES: // // The corresponding VARTYPE, or VT_NULL if error // //*************************************************************************** VARTYPE CXmlToWmi::VTFromCIMType (CIMTYPE cimtype) { VARTYPE vt = VT_NULL; switch (cimtype & ~CIM_FLAG_ARRAY) { case CIM_UINT8: vt = VT_UI1; break; case CIM_SINT8: case CIM_SINT16: vt = VT_I2; break; case CIM_UINT16: case CIM_UINT32: case CIM_SINT32: vt = VT_I4; break; case CIM_REAL32: vt = VT_R4; break; case CIM_REAL64: vt = VT_R8; break; case CIM_BOOLEAN: vt = VT_BOOL; break; case CIM_CHAR16: vt = VT_I2; break; case CIM_STRING: case CIM_UINT64: case CIM_SINT64: case CIM_DATETIME: vt = VT_BSTR; break; } return vt; } //*************************************************************************** // // HRESULT CXmlToWmi::CIMTypeFromString // // DESCRIPTION: // // Utility function to map type attribute string to its CIMTYPE equivalent // // PARAMETERS: // // bsType the type string to be mapped // // RETURN VALUES: // // The corresponding CIMTYPE, or CIM_ILLEGAL if error // //*************************************************************************** CIMTYPE CXmlToWmi::CimtypeFromString (BSTR bsType) { CIMTYPE cimtype = CIM_ILLEGAL; if (bsType) { if (0 == _wcsicmp (bsType, L"string")) cimtype = CIM_STRING; else if (0 == _wcsicmp (bsType, L"uint32")) cimtype = CIM_UINT32; else if (0 == _wcsicmp (bsType, L"boolean")) cimtype = CIM_BOOLEAN; else if (0 == _wcsicmp (bsType, L"sint32")) cimtype = CIM_SINT32; else if (0 == _wcsicmp (bsType, L"char16")) cimtype = CIM_CHAR16; else if (0 == _wcsicmp (bsType, L"uint8")) cimtype = CIM_UINT8; else if (0 == _wcsicmp (bsType, L"uint16")) cimtype = CIM_UINT16; else if (0 == _wcsicmp (bsType, L"sint16")) cimtype = CIM_SINT16; else if (0 == _wcsicmp (bsType, L"uint64")) cimtype = CIM_UINT64; else if (0 == _wcsicmp (bsType, L"sint64")) cimtype = CIM_SINT64; else if (0 == _wcsicmp (bsType, L"datetime")) cimtype = CIM_DATETIME; else if (0 == _wcsicmp (bsType, L"real32")) cimtype = CIM_REAL32; else if (0 == _wcsicmp (bsType, L"real64")) cimtype = CIM_REAL64; } return cimtype; } HRESULT CXmlToWmi::SetArraySize ( IWbemQualifierSet *pQualSet, BSTR strArraySize ) { HRESULT hr = WBEM_E_FAILED; if (strArraySize) { VARIANT curValue; VariantInit (&curValue); curValue.vt = VT_I4; curValue.lVal = wcstol (strArraySize, NULL, 0); if (0 < curValue.lVal) { if (SUCCEEDED(hr = pQualSet->Put(L"MAX", &curValue, WBEM_FLAVOR_FLAG_PROPAGATE_TO_DERIVED_CLASS| WBEM_FLAVOR_FLAG_PROPAGATE_TO_INSTANCE| WBEM_FLAVOR_NOT_OVERRIDABLE))) hr = pQualSet->Put(L"MIN", &curValue, WBEM_FLAVOR_FLAG_PROPAGATE_TO_DERIVED_CLASS| WBEM_FLAVOR_FLAG_PROPAGATE_TO_INSTANCE| WBEM_FLAVOR_NOT_OVERRIDABLE); } VariantClear (&curValue); } return hr; } HRESULT CXmlToWmi::SetReferenceClass ( IWbemQualifierSet *pQualSet, BSTR strReferenceClass ) { #define REF_STR L"ref" HRESULT hr = WBEM_E_FAILED; int strLen = wcslen(REF_STR); bool bIsStrongReference = (strReferenceClass && (0 < wcslen(strReferenceClass))); if (bIsStrongReference) strLen += wcslen(strReferenceClass) + 1; // 1 for the ":" separator WCHAR *pRef = new WCHAR [strLen + 1]; wcscpy (pRef, REF_STR); if (bIsStrongReference) { wcscat (pRef, L":"); wcscat (pRef, strReferenceClass); } VARIANT curValue; VariantInit (&curValue); curValue.vt = VT_BSTR; curValue.bstrVal = SysAllocString (pRef); delete [] pRef; hr = pQualSet->Put(L"CIMTYPE", &curValue, WBEM_FLAVOR_FLAG_PROPAGATE_TO_DERIVED_CLASS| WBEM_FLAVOR_FLAG_PROPAGATE_TO_INSTANCE| WBEM_FLAVOR_NOT_OVERRIDABLE); VariantClear (&curValue); return hr; #undef REF_STR } HRESULT CXmlToWmi::SetObjectClass ( IWbemQualifierSet *pQualSet, BSTR strReferenceClass ) { #define OBJ_STR L"obj" HRESULT hr = WBEM_E_FAILED; int strLen = wcslen(OBJ_STR); bool bIsStrongReference = (strReferenceClass && (0 < wcslen(strReferenceClass))); if (bIsStrongReference) strLen += wcslen(strReferenceClass) + 1; // 1 for the ":" separator WCHAR *pRef = new WCHAR [strLen + 1]; wcscpy (pRef, OBJ_STR); if (bIsStrongReference) { wcscat (pRef, L":"); wcscat (pRef, strReferenceClass); } VARIANT curValue; VariantInit (&curValue); curValue.vt = VT_BSTR; curValue.bstrVal = SysAllocString (pRef); delete [] pRef; hr = pQualSet->Put(L"CIMTYPE", &curValue, WBEM_FLAVOR_FLAG_PROPAGATE_TO_DERIVED_CLASS| WBEM_FLAVOR_FLAG_PROPAGATE_TO_INSTANCE| WBEM_FLAVOR_NOT_OVERRIDABLE); VariantClear (&curValue); return hr; #undef OBJ_STR } HRESULT CXmlToWmi::MapContextProperty ( IXMLDOMNode *pProperty, IWbemContext *pContext ) { HRESULT hr = WBEM_E_FAILED; BSTR strName = NULL; BSTR strType = NULL; // Get the NAMEof the property if(SUCCEEDED(hr = GetBstrAttribute (pProperty, NAME_ATTRIBUTE, &strName)) && strName) { // Get the VTTYPE of the property if(SUCCEEDED(hr = GetBstrAttribute (pProperty, VTTYPE_ATTRIBUTE, &strType)) && strType) { // Map the Property type VARTYPE vartype = VT_EMPTY; if (VT_EMPTY != (vartype = VarTypeFromString (strType))) { // Get the child element of type "VALUE" VARIANT_BOOL bHasChildNodes; if (SUCCEEDED(pProperty->hasChildNodes (&bHasChildNodes)) && (VARIANT_TRUE == bHasChildNodes)) { IXMLDOMNodeList *pNodeList = NULL; if (SUCCEEDED(pProperty->get_childNodes (&pNodeList))) { IXMLDOMNode *pNode = NULL; while (SUCCEEDED(hr) && SUCCEEDED(pNodeList->nextNode (&pNode)) &&pNode) { BSTR strNodeName = NULL; if (SUCCEEDED(pNode->get_nodeName (&strNodeName))) { if (0 == _wcsicmp(strNodeName, VALUE_TAG)) { BSTR bsValue = NULL; pNode->get_text(&bsValue); // Map the Qualifier value VARIANT value; VariantInit (&value); // Map the value to a variant if(SUCCEEDED(hr = MapContextStringValue (bsValue, value, vartype))) { // Put the value in the context hr = pContext->SetValue (strName, 0, &value); VariantClear (&value); } SysFreeString (bsValue); } SysFreeString (strNodeName); } pNode->Release (); pNode = NULL; } pNodeList->Release (); } } } SysFreeString(strType); } SysFreeString(strName); } return hr; } HRESULT CXmlToWmi::MapContextPropertyArray ( IXMLDOMNode *pProperty, IWbemContext *pContext ) { HRESULT hr = WBEM_E_FAILED; BSTR strName = NULL; BSTR strType = NULL; BSTR strArraySize = NULL; // Get the NAME of the property if(SUCCEEDED(hr = GetBstrAttribute (pProperty, NAME_ATTRIBUTE, &strName)) && strName) { // Get the VTTYPE of the property if(SUCCEEDED(hr = GetBstrAttribute (pProperty, VTTYPE_ATTRIBUTE, &strType)) && strType) { // Get the size of the array if(SUCCEEDED(hr = GetBstrAttribute (pProperty, ARRAYSIZE_ATTRIBUTE, &strArraySize)) && strArraySize) { // Map the Property type VARTYPE vartype = VT_EMPTY; if (VT_EMPTY != (vartype = VarTypeFromString (strType))) { // Get the child element of type "VALUE.ARRAY" VARIANT_BOOL bHasChildNodes; if (SUCCEEDED(pProperty->hasChildNodes (&bHasChildNodes)) && (VARIANT_TRUE == bHasChildNodes)) { IXMLDOMNodeList *pNodeList = NULL; if (SUCCEEDED(pProperty->get_childNodes (&pNodeList))) { IXMLDOMNode *pNode = NULL; while (SUCCEEDED(hr) && SUCCEEDED(pNodeList->nextNode (&pNode)) &&pNode) { BSTR strNodeName = NULL; if (SUCCEEDED(pNode->get_nodeName (&strNodeName))) { if (0 == _wcsicmp(strNodeName, VALUEARRAY_TAG)) { VARIANT value; VariantInit(&value); // Map the value to a variant if(SUCCEEDED(hr = MapContextStringArrayValue (pNode, value, vartype))) { // Put the value in the context hr = pContext->SetValue (strName, 0, &value); VariantClear (&value); } } else hr = WBEM_E_FAILED; // Parse error SysFreeString (strNodeName); } pNode->Release (); pNode = NULL; } pNodeList->Release (); } } } SysFreeString(strArraySize); } SysFreeString(strType); } SysFreeString(strName); } return hr; } //*************************************************************************** // // HRESULT CXmlToWmi::VarTypeFromString // // DESCRIPTION: // // Utility function to map type attribute string to its VARTYPE equivalent // // PARAMETERS: // // bsType the type string to be mapped // // RETURN VALUES: // // The corresponding VARTYPE, or VT_EMPTY if error // //*************************************************************************** VARTYPE CXmlToWmi::VarTypeFromString (BSTR bsType) { VARTYPE vartype = VT_EMPTY; if (bsType) { if (0 == _wcsicmp (bsType, L"VT_I4")) vartype = VT_I4; else if (0 == _wcsicmp (bsType, L"VT_R8")) vartype = VT_R8; else if (0 == _wcsicmp (bsType, L"VT_BOOL")) vartype = VT_BOOL; else if (0 == _wcsicmp (bsType, L"VT_BSTR")) vartype = VT_BSTR; } return vartype; } //*************************************************************************** // // HRESULT CXmlToWmi::MapContextStringValue // // DESCRIPTION: // // Maps XML VALUE element content into its WMI VARIANT equivalent form // // PARAMETERS: // // bsValue the VALUE element content // curValue Placeholder for new value (set on return) // cimtype for mapping purposes // // RETURN VALUES: // // //*************************************************************************** HRESULT CXmlToWmi::MapContextStringValue (BSTR bsValue, VARIANT &curValue, VARTYPE vartype) { HRESULT hr = WBEM_E_TYPE_MISMATCH; // We're assuming it's not an array switch (vartype) { // RAJESHR - more rigorous syntax checking case VT_I4: { VariantClear (&curValue); curValue.vt = VT_I4; curValue.lVal = wcstol (bsValue, NULL, 0); hr = S_OK; } break; case VT_R8: { VariantClear (&curValue); curValue.vt = VT_R8; curValue.dblVal = wcstod (bsValue, NULL); hr = S_OK; } break; case VT_BOOL: { VariantClear (&curValue); curValue.vt = VT_BOOL; curValue.boolVal = (0 == _wcsicmp (bsValue, L"TRUE")) ? VARIANT_TRUE : VARIANT_FALSE; hr = S_OK; } break; case VT_BSTR: { VariantClear (&curValue); curValue.vt = VT_BSTR; curValue.bstrVal = SysAllocString (bsValue); hr = S_OK; } break; } return hr; } //*************************************************************************** // // HRESULT CXmlToWmi::MapContextStringArrayValue // // DESCRIPTION: // // Maps XML VALUE.ARRAY element content into its WMI VARIANT equivalent form // // PARAMETERS: // // pValueNode the VALUE.ARRAY node // curValue Placeholder for new value (set on return) // cimtype for mapping purposes // // RETURN VALUES: // // //*************************************************************************** HRESULT CXmlToWmi::MapContextStringArrayValue ( IXMLDOMNode *pValueNode, VARIANT &curValue, VARTYPE vartype ) { HRESULT hr = WBEM_E_TYPE_MISMATCH; // Build a safearray value from the node list IXMLDOMNodeList *pValueList = NULL; if (SUCCEEDED (pValueNode->get_childNodes (&pValueList))) { long length = 0; pValueList->get_length (&length); SAFEARRAYBOUND rgsabound [1]; rgsabound [0].lLbound = 0; rgsabound [0].cElements = length; SAFEARRAY *pArray = NULL; if(pArray = SafeArrayCreate (vartype, 1, rgsabound)) { IXMLDOMNode *pValue = NULL; long ix = 0; bool error = false; while (!error && SUCCEEDED(pValueList->nextNode(&pValue)) && pValue) { BSTR strValName = NULL; if (SUCCEEDED(pValue->get_nodeName (&strValName))) { if (0 == _wcsicmp (strValName, VALUE_TAG)) { BSTR bsValue = NULL; pValue->get_text (&bsValue); if(FAILED(MapContextStringValueIntoArray (bsValue, pArray, &ix, vartype))) error = true; SysFreeString (bsValue); ix++; } else { // unexpected element error = true; } SysFreeString (strValName); } pValue->Release (); pValue = NULL; } if (error) SafeArrayDestroy(pArray); else { curValue.vt = VT_ARRAY|vartype; curValue.parray = pArray; hr = S_OK; } } else hr = E_OUTOFMEMORY; pValueList->Release(); } return hr; } //*************************************************************************** // // HRESULT CXmlToWmi::MapContextStringValueIntoArray // // DESCRIPTION: // // Maps XML VALUE.ARRAY/VALUE element content into its WMI VARIANT equivalent form // // PARAMETERS: // // bsValue the VALUE element content // pArray SAFEARRAY in which to map the value // ix index to map the value into // vt VARTYPE of the SAFEARRAY // cimtype for mapping purposes // // RETURN VALUES: // // //*************************************************************************** HRESULT CXmlToWmi::MapContextStringValueIntoArray ( BSTR bsValue, SAFEARRAY *pArray, long *ix, VARTYPE vt) { HRESULT hr = E_FAIL; switch (vt) { case VT_I4: { long lVal = wcstol (bsValue, NULL, 0); hr = SafeArrayPutElement (pArray, ix, &lVal); } break; case VT_R8: { double dblVal = wcstod (bsValue, NULL); hr = SafeArrayPutElement (pArray, ix, &dblVal); } break; case VT_BOOL: { VARIANT_BOOL boolVal = (0 == _wcsicmp (bsValue, L"TRUE")) ? VARIANT_TRUE : VARIANT_FALSE; hr = SafeArrayPutElement (pArray, ix, &boolVal); } break; case VT_BSTR: hr = SafeArrayPutElement (pArray, ix, bsValue); break; } return hr; }