//*************************************************************************** // // Copyright (c) 1997-1999 Microsoft Corporation // // WBEM2XML.CPP // // alanbos 18-Feb-98 Created. // // The WBEM -> XML translator // //*************************************************************************** #include "precomp.h" static BYTE NEWLINE [] = { 0x0D, 0x00, 0x0A, 0x00 }; static BYTE UTF16SIG [] = { 0xFF, 0xFE }; static OLECHAR *CDATASTART = OLESTR(""); static OLECHAR *AMPERSAND = OLESTR("&"); static OLECHAR *LEFTCHEVRON = OLESTR("<"); static OLECHAR *RIGHTCHEVRON = OLESTR(">"); //*************************************************************************** // // CWmiToXml::CWmiToXml // // DESCRIPTION: // // Constructor: Used for GetObject invocations // //*************************************************************************** CWmiToXml::CWmiToXml(BSTR bsNamespacePath, IStream *pStream, IWbemClassObject *pObject, VARIANT_BOOL bAllowWMIExtensions, WmiXMLFilterEnum iQualifierFilter, VARIANT_BOOL bHostFilter, WmiXMLDTDVersionEnum iDTDVersion, VARIANT_BOOL bNamespaceInDeclGroup, WmiXMLClassOriginFilterEnum iClassOriginFilter, WmiXMLDeclGroupTypeEnum iDeclGroupType) { m_pStream = pStream; m_pStream->AddRef (); m_pObject = pObject; m_pObject->AddRef (); m_pEnum = NULL; m_bAllowWMIExtensions = bAllowWMIExtensions; m_iQualifierFilter = iQualifierFilter; m_iDTDVersion = iDTDVersion; m_bHostFilter = bHostFilter; m_bIsClass = false; m_bsNamespacePath = SysAllocString(bsNamespacePath); m_bNamespaceInDeclGroup = bNamespaceInDeclGroup; m_iClassOriginFilter = iClassOriginFilter; m_iDeclGroupType = iDeclGroupType; } //*************************************************************************** // // CWmiToXml::CWmiToXml // // DESCRIPTION: // // Constructor: Used for ExecQuery invocations // //*************************************************************************** CWmiToXml::CWmiToXml(BSTR bsNamespacePath, IStream *pStream, IEnumWbemClassObject *pEnum, VARIANT_BOOL bAllowWMIExtensions, WmiXMLFilterEnum iQualifierFilter, VARIANT_BOOL bHostFilter, WmiXMLDTDVersionEnum iDTDVersion, VARIANT_BOOL bNamespaceInDeclGroup, WmiXMLClassOriginFilterEnum iClassOriginFilter, WmiXMLDeclGroupTypeEnum iDeclGroupType) { m_pStream = pStream; m_pStream->AddRef (); m_pEnum = pEnum; m_pEnum->AddRef (); m_pObject = NULL; m_bAllowWMIExtensions = bAllowWMIExtensions; m_iQualifierFilter = iQualifierFilter; m_iDTDVersion = iDTDVersion; m_bHostFilter = bHostFilter; m_bIsClass = false; m_bsNamespacePath = SysAllocString(bsNamespacePath); m_bNamespaceInDeclGroup = bNamespaceInDeclGroup; m_iClassOriginFilter = iClassOriginFilter; m_iDeclGroupType = iDeclGroupType; } //*************************************************************************** // // CWmiToXml::~CWmiToXml // // DESCRIPTION: // // Destructor. // //*************************************************************************** CWmiToXml::~CWmiToXml(void) { if (m_pStream) m_pStream->Release (); if (m_pObject) m_pObject->Release (); if (m_pEnum) m_pEnum->Release (); SysFreeString (m_bsNamespacePath); } STDMETHODIMP CWmiToXml::MapCommonHeaders (BSTR pszSchemaURL) { // WRITESIG WRITEBSTR(OLESTR("")) WRITENL if (pszSchemaURL) { WRITEBSTR(OLESTR("")) WRITENL } WRITEBSTR(OLESTR("")) WRITENL WRITEBSTR(OLESTR("")) WRITENL return S_OK; } STDMETHODIMP CWmiToXml::MapDeclGroupHeaders () { switch(m_iDeclGroupType) { case wmiXMLDeclGroup: WRITEBSTR(OLESTR("")) WRITENL if (m_bNamespaceInDeclGroup == VARIANT_TRUE) MapNamespacePath (m_bsNamespacePath); break; case wmiXMLDeclGroupWithName: WRITEBSTR(OLESTR("")) WRITENL if (m_bNamespaceInDeclGroup == VARIANT_TRUE) MapNamespacePath (m_bsNamespacePath); break; case wmiXMLDeclGroupWithPath: WRITEBSTR(OLESTR("")) WRITENL break; } return S_OK; } STDMETHODIMP CWmiToXml::MapDeclGroupTrailers () { switch(m_iDeclGroupType) { case wmiXMLDeclGroup: WRITEBSTR(OLESTR("")) WRITENL break; case wmiXMLDeclGroupWithName: WRITEBSTR(OLESTR("")) WRITENL break; case wmiXMLDeclGroupWithPath: WRITEBSTR(OLESTR("")) WRITENL break; } return S_OK; } STDMETHODIMP CWmiToXml::MapCommonTrailers () { WRITEBSTR(OLESTR("")) WRITEBSTR(OLESTR("")) return S_OK; } STDMETHODIMP CWmiToXml::MapEnum (BSTR pszSchemaURL) { HRESULT hr = S_OK; ULONG dummy = 0; // Map the Headers MapCommonHeaders(pszSchemaURL); // We need to optimize on DeclGroup generation in case of an Association query where // the namespaces of the resulting objects might not be unique. In this case, the best alogirithm // would be the one that sorts the resulting objects into different namespaces and generates on declgroup // declaration per unique namespace. However, this requires a bidirectional enumerator which we want // to avoid due to high memory consumption. Hence we use a semi-optimal algorithm in which the rule is // we do not generate a new DeclGroup if the namespace of the current object is the same as that of // the previous object in the output (or the enumerator). BSTR strLastNamespacePath = NULL; while (SUCCEEDED(hr) && SUCCEEDED(hr = m_pEnum->Next (INFINITE, 1, &m_pObject, &dummy)) && dummy != 0) { BSTR strCurrentNamespace = GetNamespace(m_pObject); if(strCurrentNamespace) { if( !strLastNamespacePath || _wcsicmp(strLastNamespacePath, strCurrentNamespace) != 0) { if(strLastNamespacePath) MapDeclGroupTrailers(); MapDeclGroupHeaders(); if (strLastNamespacePath) SysFreeString(strLastNamespacePath); strLastNamespacePath = SysAllocString(strCurrentNamespace); } SysFreeString(strCurrentNamespace); // Map the object to XML hr = MapObjectWithoutHeaders (); } m_pObject->Release (); m_pObject = NULL; } if(strLastNamespacePath) { MapDeclGroupTrailers(); SysFreeString(strLastNamespacePath); } // Write the trailers MapCommonTrailers(); LARGE_INTEGER offset; offset.LowPart = offset.HighPart = 0; m_pStream->Seek (offset, STREAM_SEEK_SET, NULL); return hr; } STDMETHODIMP CWmiToXml::MapObject (BSTR pszSchemaURL) { // Map the Headers MapCommonHeaders(pszSchemaURL); MapDeclGroupHeaders(); HRESULT hr = MapObjectWithoutHeaders(); // Write the trailers MapDeclGroupTrailers(); MapCommonTrailers(); LARGE_INTEGER offset; offset.LowPart = offset.HighPart = 0; m_pStream->Seek (offset, STREAM_SEEK_SET, NULL); return hr; } STDMETHODIMP CWmiToXml::MapObjectWithoutHeaders () { HRESULT hr = WBEM_E_FAILED; IWbemQualifierSet *pQualSet= NULL; m_pObject->GetQualifierSet (&pQualSet); VARIANT var; VariantInit (&var); // Is this a class or an instance long flav = 0; if (SUCCEEDED (m_pObject->Get(L"__GENUS", 0, &var, NULL, &flav))) m_bIsClass = (WBEM_GENUS_CLASS == var.lVal); switch(m_iDeclGroupType) { case wmiXMLDeclGroup: WRITEBSTR(OLESTR("")); WRITENL hr = (m_bIsClass) ? MapClass (pQualSet) : MapInstance (pQualSet); WRITEBSTR(OLESTR("")); WRITENL break; case wmiXMLDeclGroupWithName: WRITEBSTR(OLESTR("")); WRITENL hr = (m_bIsClass) ? MapClass (pQualSet) : MapNamedInstance (pQualSet); WRITEBSTR(OLESTR("")); WRITENL break; case wmiXMLDeclGroupWithPath: WRITEBSTR(OLESTR("")); WRITENL hr = (m_bIsClass) ? MapWithPathClass (pQualSet) : MapWithPathInstance (pQualSet); WRITEBSTR(OLESTR("")); WRITENL break; } if (pQualSet) pQualSet->Release (); VariantClear (&var); return hr; } STDMETHODIMP CWmiToXml::MapWithPathClass (IWbemQualifierSet *pQualSet) { // First map an element of type CLASSPATH //========================================== HRESULT hr = WBEM_E_FAILED; // Get the __PATH of the object VARIANT var; VariantInit (&var); if (WBEM_S_NO_ERROR == m_pObject->Get(L"__PATH", 0, &var, NULL, NULL)) { // Parse the object path CObjectPathParser pathParser (e_ParserAcceptRelativeNamespace); ParsedObjectPath *pParsedPath; pathParser.Parse (var.bstrVal, &pParsedPath) ; if (pParsedPath) { if(SUCCEEDED(MapClassPath (pParsedPath))) hr = MapClass(pQualSet); pathParser.Free(pParsedPath); } VariantClear(&var); } return hr; } STDMETHODIMP CWmiToXml::MapClass (IWbemQualifierSet *pQualSet) { HRESULT hr = WBEM_E_FAILED; VARIANT var; VariantInit (&var); long flav = 0; BSTR bsClass = NULL; BSTR bsSuperClass = NULL; // Get the class attribute if (WBEM_S_NO_ERROR == m_pObject->Get(L"__CLASS", 0, &var, NULL, &flav)) if ((VT_BSTR == var.vt) && (NULL != var.bstrVal) && (wcslen (var.bstrVal) > 0)) bsClass = SysAllocString (var.bstrVal); VariantClear (&var); // Get the superclass attribute if (WBEM_S_NO_ERROR == m_pObject->Get(L"__SUPERCLASS", 0, &var, NULL, &flav)) if ((VT_BSTR == var.vt) && (NULL != var.bstrVal) && (wcslen (var.bstrVal) > 0)) bsSuperClass = SysAllocString (var.bstrVal); VariantClear (&var); if (pQualSet) { WRITEBSTR(OLESTR("")) WRITENL if (SUCCEEDED(hr = MapQualifiers (pQualSet))) if (SUCCEEDED(hr = MapProperties())) hr = MapMethods (); WRITEBSTR(OLESTR("")) WRITENL } SysFreeString (bsClass); SysFreeString (bsSuperClass); return hr; } STDMETHODIMP CWmiToXml::MapClassPath (ParsedObjectPath *pParsedPath) { HRESULT hr = WBEM_E_FAILED; WRITEBSTR(OLESTR("")) WRITENL MapNamespacePath (pParsedPath); WRITENL MapClassName (pParsedPath->m_pClass); WRITEBSTR(OLESTR("")) return S_OK; } STDMETHODIMP CWmiToXml::MapLocalClassPath (ParsedObjectPath *pParsedPath) { HRESULT hr = WBEM_E_FAILED; WRITEBSTR(OLESTR("")) WRITENL MapLocalNamespacePath (pParsedPath); WRITENL MapClassName (pParsedPath->m_pClass); WRITEBSTR(OLESTR("")) return S_OK; } STDMETHODIMP CWmiToXml::MapClassName (BSTR bsClassName) { WRITEBSTR(OLESTR("")) return S_OK; } STDMETHODIMP CWmiToXml::MapNamedInstance (IWbemQualifierSet *pQualSet) { // First map an element of type INSTANCENAME //========================================== HRESULT hr = WBEM_E_FAILED; // Get the __RELPATH of the object VARIANT var; VariantInit (&var); if (WBEM_S_NO_ERROR == m_pObject->Get(L"__PATH", 0, &var, NULL, NULL)) { // Parse the object path CObjectPathParser pathParser (e_ParserAcceptRelativeNamespace); ParsedObjectPath *pParsedPath; pathParser.Parse (var.bstrVal, &pParsedPath) ; if (pParsedPath) { if(SUCCEEDED(MapInstanceName (pParsedPath))) { hr = MapInstance(pQualSet); } pathParser.Free(pParsedPath); } VariantClear(&var); } return hr; } STDMETHODIMP CWmiToXml::MapWithPathInstance (IWbemQualifierSet *pQualSet) { // First map an element of type INSTANCEPATH //========================================== HRESULT hr = WBEM_E_FAILED; // Get the __RELPATH of the object VARIANT var; VariantInit (&var); if (WBEM_S_NO_ERROR == m_pObject->Get(L"__PATH", 0, &var, NULL, NULL)) { // Parse the object path CObjectPathParser pathParser (e_ParserAcceptRelativeNamespace); ParsedObjectPath *pParsedPath; pathParser.Parse (var.bstrVal, &pParsedPath) ; if (pParsedPath) { if(SUCCEEDED(MapInstancePath (pParsedPath))) hr = MapInstance(pQualSet); pathParser.Free(pParsedPath); } VariantClear(&var); } return hr; } STDMETHODIMP CWmiToXml::MapInstance (IWbemQualifierSet *pQualSet) { HRESULT hr = WBEM_E_FAILED; if (pQualSet) { WRITEBSTR(OLESTR("Get(L"__CLASS", 0, &var, NULL, &flav)) if ((VT_BSTR == var.vt) && (NULL != var.bstrVal) && (wcslen (var.bstrVal) > 0)) bsClass = SysAllocString (var.bstrVal); VariantClear (&var); // Map the class name // Write the CLASSNAME WRITEBSTR(bsClass) WRITEBSTR(OLESTR("\">")) WRITENL if (SUCCEEDED (hr = MapQualifiers (pQualSet))) hr = MapProperties (); WRITEBSTR(OLESTR("")) WRITENL SysFreeString (bsClass); } return hr; } STDMETHODIMP CWmiToXml::MapInstancePath (ParsedObjectPath *pParsedPath) { WRITEBSTR(OLESTR("")) WRITENL MapNamespacePath (pParsedPath); WRITENL MapInstanceName (pParsedPath); WRITENL WRITEBSTR(OLESTR("")) return S_OK; } STDMETHODIMP CWmiToXml::MapLocalInstancePath (ParsedObjectPath *pParsedPath) { WRITEBSTR(OLESTR("")) WRITENL MapLocalNamespacePath (pParsedPath); WRITENL MapInstanceName (pParsedPath); WRITENL WRITEBSTR(OLESTR("")) return S_OK; } STDMETHODIMP CWmiToXml::MapInstanceName (ParsedObjectPath *pParsedPath) { WRITEBSTR(OLESTR("m_pClass) WRITEBSTR(OLESTR("\">")) WRITENL // 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 WRITENL MapKeyValue ((pParsedPath->m_paKeys [0])->m_vValue); WRITENL } else { for (DWORD numKey = 0; numKey < pParsedPath->m_dwNumKeys; numKey++) { WRITEBSTR(OLESTR("m_paKeys [numKey])->m_pName) WRITEBSTR(OLESTR("\">")) WRITENL // Write the key value MapKeyValue ((pParsedPath->m_paKeys [numKey])->m_vValue); WRITENL WRITEBSTR(OLESTR("")) WRITENL } } } WRITEBSTR(OLESTR("")) return S_OK; } STDMETHODIMP CWmiToXml::MapNamespacePath (BSTR bsNamespacePath) { CObjectPathParser pathParser (e_ParserAcceptRelativeNamespace); ParsedObjectPath *pParsedPath; pathParser.Parse (bsNamespacePath, &pParsedPath) ; if (pParsedPath) { MapNamespacePath (pParsedPath); delete pParsedPath; } return S_OK; } STDMETHODIMP CWmiToXml::MapNamespacePath (ParsedObjectPath *pParsedPath) { WRITEBSTR(OLESTR("")) WRITENL WRITEBSTR(OLESTR("")) HRESULT hr = WBEM_S_NO_ERROR; if (VARIANT_TRUE == m_bHostFilter) { if (pParsedPath->m_pServer && _wcsicmp(pParsedPath->m_pServer, L".")) WRITEWSTR(pParsedPath->m_pServer) else // Use GetComputerName to get the name of the machine { LPWSTR pszHostName = NULL; if(pszHostName = GetHostName()) { WRITEBSTR(pszHostName) delete [] pszHostName; } else hr = E_FAIL; } } else WRITEBSTR(OLESTR(".")) WRITEBSTR(OLESTR("")) WRITENL // If this value has no namespace component use the object's namespace path if (0 < pParsedPath->m_dwNumNamespaces) MapLocalNamespacePath (pParsedPath); WRITEBSTR(OLESTR("")) WRITENL return hr; } STDMETHODIMP CWmiToXml::MapLocalNamespacePath (ParsedObjectPath *pObjectPath) { WRITEBSTR(OLESTR("")) WRITENL for (DWORD dwIndex = 0; dwIndex < pObjectPath->m_dwNumNamespaces; dwIndex++) { WRITEBSTR(OLESTR("m_paNamespaces [dwIndex]) WRITEBSTR(OLESTR("\"/>")) WRITENL } WRITEBSTR(OLESTR("")) return WBEM_S_NO_ERROR; } STDMETHODIMP CWmiToXml::MapReference (BSTR name, VARIANT &var, long flavor) { HRESULT hr = WBEM_S_NO_ERROR; IWbemQualifierSet *pQualSet = NULL; if (WBEM_S_NO_ERROR == m_pObject->GetPropertyQualifierSet (name, &pQualSet)) { WRITEBSTR(OLESTR("GetPropertyOrigin (name, &propertyOrigin)) { MapClassOrigin (propertyOrigin); SysFreeString(propertyOrigin); } MapLocal (flavor); // The strong class of this property MapStrongType (pQualSet); WRITEBSTR(OLESTR(">")) WRITENL // Map the qualifiers MapQualifiers (pQualSet); pQualSet->Release (); MapReferenceValue (var); WRITEBSTR(OLESTR("")) WRITENL } 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. // //*************************************************************************** ParsedObjectPath *CWmiToXml::IsReference (VARIANT &var) { ParsedObjectPath *pObjectPath = NULL; // TODO - 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)) { bool isValidPath = false; // 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)) isValidPath = true; else { // A potential local class path // TODO - try grabbing the class to see if it exists in // the current namespace. } } } if (!isValidPath) { // Reject for now - too ambiguous parser.Free(pObjectPath); pObjectPath = NULL; } } return pObjectPath; } void CWmiToXml::MapReferenceValue (VARIANT &var) { // 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) ; if ((0 == status) && pObjectPath && (pObjectPath->IsClass () || pObjectPath->IsInstance ())) MapReferenceValue (pObjectPath); if (pObjectPath) parser.Free(pObjectPath); } } void CWmiToXml::MapReferenceValue (ParsedObjectPath *pObjectPath) { WRITEBSTR(OLESTR("")) WRITENL 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 (pObjectPath); else if (bIsRelativePath) MapLocalClassPath (pObjectPath); else MapClassName (pObjectPath->m_pClass); } else if (pObjectPath->IsInstance ()) { if (bIsAbsolutePath) MapInstancePath (pObjectPath); else if (bIsRelativePath) MapLocalInstancePath (pObjectPath); else MapInstanceName (pObjectPath); } WRITENL WRITEBSTR(OLESTR("")) } STDMETHODIMP CWmiToXml::MapQualifiers ( IWbemQualifierSet *pQualSet, IWbemQualifierSet *pQualSet2) { if (wmiXMLFilterNone != m_iQualifierFilter) { // Map the requested filter to the flags value - default is ALL LONG lFlags = 0; if (wmiXMLFilterLocal == m_iQualifierFilter) lFlags = WBEM_FLAG_LOCAL_ONLY; else if (wmiXMLFilterPropagated == m_iQualifierFilter) lFlags = WBEM_FLAG_PROPAGATED_ONLY; 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 (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 (name, flavor, var); SysFreeString (name); name = NULL; VariantClear (&var); } pQualSet2->EndEnumeration (); } } return WBEM_S_NO_ERROR; } void CWmiToXml::MapLocal (long flavor) { // default is false if (WBEM_FLAVOR_ORIGIN_PROPAGATED == (WBEM_FLAVOR_MASK_ORIGIN & flavor)) WRITEBSTR(OLESTR(" PROPAGATED=\"true\"")) } STDMETHODIMP CWmiToXml::MapQualifier (BSTR name, long flavor, VARIANT &var) { // The qualifier name WRITEBSTR(OLESTR("")) WRITENL // Now map the value MapValue (var); WRITEBSTR(OLESTR("")) WRITENL return WBEM_S_NO_ERROR; } STDMETHODIMP CWmiToXml::MapValue (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("")) for (long i = 0; i <= uBound; i++) { WRITEBSTR(OLESTR("")) // Write the value itself switch (var.vt & ~VT_ARRAY) { case VT_I4: { long val = 0; SafeArrayGetElement (var.parray, &i, &val); MapLongValue (val); } break; case VT_R8: { double val = 0; SafeArrayGetElement (var.parray, &i, &val); MapDoubleValue (val); } break; case VT_BOOL: { VARIANT_BOOL val = 0; SafeArrayGetElement (var.parray, &i, &val); MapBoolValue ((val) ? true : false); } break; case VT_BSTR: { BSTR val = NULL; SafeArrayGetElement (var.parray, &i, &val); MapStringValue (val); SysFreeString (val); } break; } WRITEBSTR(OLESTR("")) WRITENL } WRITEBSTR(OLESTR("")) } else { // Simple value WRITEBSTR(OLESTR("")) switch (var.vt) { case VT_I4: MapLongValue (var.lVal); break; case VT_R8: MapDoubleValue (var.dblVal); break; case VT_BOOL: MapBoolValue ((var.boolVal) ? true : false); break; case VT_BSTR: MapStringValue (var.bstrVal); break; } WRITEBSTR(OLESTR("")) } WRITENL return WBEM_S_NO_ERROR; } STDMETHODIMP CWmiToXml::MapKeyValue (VARIANT &var) { ParsedObjectPath *pObjectPath = NULL; if (pObjectPath = IsReference (var)) { MapReferenceValue (pObjectPath); WRITENL delete pObjectPath; } else { // Simple value WRITEBSTR(OLESTR("")) MapLongValue (var.lVal); break; case VT_R8: WRITEBSTR(OLESTR(" VALUETYPE=\"numeric\">")) MapDoubleValue (var.dblVal); break; case VT_BOOL: WRITEBSTR(OLESTR(" VALUETYPE=\"boolean\">")) MapBoolValue ((var.boolVal) ? true : false); break; case VT_BSTR: WRITEBSTR(OLESTR(">")) MapStringValue (var.bstrVal); break; } WRITEBSTR(OLESTR("")) } return WBEM_S_NO_ERROR; } STDMETHODIMP CWmiToXml::MapProperties () { m_pObject->BeginEnumeration (WBEM_FLAG_NONSYSTEM_ONLY); VARIANT var; VariantInit (&var); long flavor = 0; CIMTYPE cimtype = CIM_ILLEGAL; BSTR name = NULL; while (WBEM_S_NO_ERROR == m_pObject->Next (0, &name, &var, &cimtype, &flavor)) { switch (cimtype & ~CIM_FLAG_ARRAY) { case CIM_OBJECT: MapObjectProperty (name, var, (cimtype & CIM_FLAG_ARRAY) ? true : false, flavor); break; case CIM_REFERENCE: MapReference (name, var, flavor); break; default: MapProperty (name, var, cimtype & ~CIM_FLAG_ARRAY, (cimtype & CIM_FLAG_ARRAY) ? true : false, flavor); break; } SysFreeString (name); VariantClear (&var); } m_pObject->EndEnumeration (); return WBEM_S_NO_ERROR; } STDMETHODIMP CWmiToXml::MapProperty (BSTR name, VARIANT &var, CIMTYPE cimtype, bool isArray, long flavor) { HRESULT hr = WBEM_S_NO_ERROR; IWbemQualifierSet *pQualSet= NULL; if (WBEM_S_NO_ERROR == (hr = m_pObject->GetPropertyQualifierSet (name, &pQualSet))) { // The property name if (isArray) WRITEBSTR(OLESTR("GetPropertyOrigin (name, &propertyOrigin)) { MapClassOrigin (propertyOrigin); SysFreeString(propertyOrigin); } MapLocal (flavor); // The property CIM type hr = MapType (cimtype); // Map the Array Size attribute if this is an array type if (isArray) MapArraySize (pQualSet); WRITEBSTR(OLESTR(">")) WRITENL // Map the qualifiers (note that system properties have no qualifiers) MapQualifiers (pQualSet); // Now map the value hr = MapValue (cimtype, isArray, var); if (isArray) WRITEBSTR(OLESTR("")) else WRITEBSTR(OLESTR("")) WRITENL pQualSet->Release (); } return hr; } STDMETHODIMP CWmiToXml::MapObjectProperty (BSTR name, VARIANT &var, bool isArray, long flavor) { 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 = m_pObject->GetPropertyQualifierSet (name, &pQualSet))) { // The property name if (isArray) WRITEBSTR(OLESTR("GetPropertyOrigin (name, &propertyOrigin)) { MapClassOrigin (propertyOrigin); SysFreeString(propertyOrigin); } MapLocal (flavor); MapStrongType (pQualSet); if (isArray) MapArraySize (pQualSet); WRITEBSTR(OLESTR(">")) WRITENL MapQualifiers (pQualSet); // Now map the value hr = MapEmbeddedObjectValue (isArray, var); if (isArray) WRITEBSTR(OLESTR("")) else WRITEBSTR(OLESTR("")) WRITENL pQualSet->Release (); } } return hr; } bool CWmiToXml::PropertyIsLocal (BSTR name, long flavor, IWbemQualifierSet *pQualSet) { bool isLocal = false; if (WBEM_FLAVOR_ORIGIN_LOCAL == (WBEM_FLAVOR_MASK_ORIGIN & flavor)) isLocal = true; else { // If we are dealing with a class we are done if (!m_bIsClass) { // Check if any of the qualifiers have the local bit set pQualSet->BeginEnumeration (WBEM_FLAG_LOCAL_ONLY); if (WBEM_S_NO_ERROR == pQualSet->Next (0, NULL, NULL, NULL)) isLocal = true; else { // NOTE this needs RAID #29202 to be implemented for all this to work because // currently deletion of a property from an instance ALWAYS returns // WBEM_S_RESET_TO_DEFAULT. IWbemClassObject *pClone = NULL; if (WBEM_S_NO_ERROR == m_pObject->Clone (&pClone)) { // If delete returns WBEM_S_RESET_TO_DEFAULT, we may have // an override deal here. if (WBEM_S_RESET_TO_DEFAULT == pClone->Delete (name)) { isLocal = true; } pClone->Release (); } } pQualSet->EndEnumeration (); } } return isLocal; } void CWmiToXml::MapArraySize (IWbemQualifierSet *pQualSet) { // TODO - 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 (var.lVal); WRITEBSTR(OLESTR("\"")) } VariantClear (&var); } void CWmiToXml::MapStrongType (IWbemQualifierSet *pQualSet) { WRITEBSTR(OLESTR(" REFERENCECLASS=\"")) GetClassName (pQualSet); WRITEBSTR(OLESTR("\"")) } void CWmiToXml::GetClassName (IWbemQualifierSet *pQualSet) { VARIANT var; VariantClear (&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 = new OLECHAR[classLen + 1]; wcscpy (classPtr, ptr+1); BSTR pszClass = SysAllocString(classPtr); delete [] classPtr; classPtr = NULL; WRITEBSTR(pszClass) SysFreeString(pszClass); } } VariantClear(&var); } STDMETHODIMP CWmiToXml::MapType (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 (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("")) for (long i = 0; i <= uBound; i++) { WRITEBSTR(OLESTR("")) switch (cimtype) { case CIM_UINT8: { unsigned char val = 0; SafeArrayGetElement (var.parray, &i, &val); MapByteValue (val); } break; case CIM_SINT8: case CIM_SINT16: { short val = 0; SafeArrayGetElement (var.parray, &i, &val); MapShortValue (val); } break; case CIM_UINT16: case CIM_UINT32: case CIM_SINT32: { long val = 0; SafeArrayGetElement (var.parray, &i, &val); MapLongValue (val); } break; case CIM_REAL32: { float val = 0; SafeArrayGetElement (var.parray, &i, &val); MapFloatValue (val); } break; case CIM_REAL64: { double val = 0; SafeArrayGetElement (var.parray, &i, &val); MapDoubleValue (val); } break; case CIM_BOOLEAN: { VARIANT_BOOL val = 0; SafeArrayGetElement (var.parray, &i, &val); MapBoolValue ((val)? true : false); } break; case CIM_CHAR16: { long val = 0; SafeArrayGetElement (var.parray, &i, &val); MapCharValue (val); } break; case CIM_STRING: { BSTR val = NULL; SafeArrayGetElement (var.parray, &i, &val); MapStringValue (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("")) WRITENL } WRITEBSTR(OLESTR("")) } else { // Simple value WRITEBSTR(OLESTR("")) switch (cimtype) { case CIM_UINT8: MapByteValue (var.bVal); break; case CIM_SINT8: case CIM_SINT16: MapShortValue (var.iVal); break; case CIM_UINT16: case CIM_UINT32: case CIM_SINT32: MapLongValue (var.lVal); break; case CIM_REAL32: MapFloatValue (var.fltVal); break; case CIM_REAL64: MapDoubleValue (var.dblVal); break; case CIM_BOOLEAN: MapBoolValue ((var.boolVal) ? true : false); break; case CIM_CHAR16: MapCharValue (var.iVal); break; case CIM_STRING: MapStringValue (var.bstrVal); break; case CIM_UINT64: case CIM_SINT64: case CIM_DATETIME: WRITEBSTR(var.bstrVal) break; } WRITEBSTR(OLESTR("")) WRITENL } WRITENL return WBEM_S_NO_ERROR; } STDMETHODIMP CWmiToXml::MapEmbeddedObjectValue (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("")) 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))) { CWmiToXml wbemToXml (NULL, m_pStream, pEmbeddedObject, m_bAllowWMIExtensions, m_iQualifierFilter, m_bHostFilter, m_iDTDVersion, m_bNamespaceInDeclGroup, m_iClassOriginFilter, m_iDeclGroupType); hr = wbemToXml.MapObjectWithoutHeaders(); pEmbeddedObject->Release(); } pNextElement->Release(); pNextElement = NULL; } } WRITEBSTR(OLESTR("")) } else { // TODO - need different constructor // here to say "just generate a VALUE.OBJECT rather // than a DECLGROUP" IWbemClassObject *pEmbeddedObject = NULL; if(SUCCEEDED(hr = (var.punkVal)->QueryInterface(IID_IWbemClassObject, (LPVOID *)&pEmbeddedObject))) { CWmiToXml wbemToXml (NULL, m_pStream, pEmbeddedObject, m_bAllowWMIExtensions, m_iQualifierFilter, m_bHostFilter, m_iDTDVersion, m_bNamespaceInDeclGroup, m_iClassOriginFilter, m_iDeclGroupType); hr = wbemToXml.MapObjectWithoutHeaders(); pEmbeddedObject->Release(); } } return hr; } STDMETHODIMP CWmiToXml::MapMethods () { m_pObject->BeginMethodEnumeration (0); BSTR name = NULL; IWbemClassObject *pInParams = NULL; IWbemClassObject *pOutParams = NULL; while (WBEM_S_NO_ERROR == m_pObject->NextMethod (0, &name, &pInParams, &pOutParams)) { MapMethod (name, pInParams, pOutParams); if (pInParams) { pInParams->Release (); pInParams = NULL; } if (pOutParams) { pOutParams->Release (); pOutParams = NULL; } SysFreeString (name); } m_pObject->EndMethodEnumeration (); return WBEM_S_NO_ERROR; } void CWmiToXml::MapMethod (BSTR name, IWbemClassObject *pInParams, IWbemClassObject *pOutParams) { // The method name WRITEBSTR(OLESTR("Get (L"ReturnValue", 0, NULL, &returnCimtype, NULL))) MapType(returnCimtype); // The class origin BSTR methodOrigin = NULL; if (WBEM_S_NO_ERROR == m_pObject->GetMethodOrigin (name, &methodOrigin)) { MapClassOrigin (methodOrigin); SysFreeString(methodOrigin); } WRITEBSTR(OLESTR(">")) WRITENL // Now do the qualifiers IWbemQualifierSet *pQualSet = NULL; if (WBEM_S_NO_ERROR == m_pObject->GetMethodQualifierSet (name, &pQualSet)) { MapQualifiers (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(nextInParamName, pParamQualSet, cimtype); } } else { if (WBEM_S_NO_ERROR == pOutParams->Get (nextOutParamName, 0, &var, &cimtype, NULL)) { pOutParams->GetPropertyQualifierSet (nextOutParamName, &pParamQualSet); MapParameter(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(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 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; } WRITEBSTR(OLESTR("")) WRITENL } void CWmiToXml::MapClassOrigin (BSTR &classOrigin) { if ( (m_bIsClass && (m_iClassOriginFilter & wmiXMLClassOriginFilterClass)) || ((!m_bIsClass) && (m_iClassOriginFilter & wmiXMLClassOriginFilterInstance)) ) { WRITEBSTR(OLESTR(" CLASSORIGIN=\"")) WRITEBSTR(classOrigin) WRITEBSTR(OLESTR("\"")) } } void CWmiToXml::MapParameter (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("")) WRITENL // Map the qualifiers of the parameter if (pQualSet || pQualSet2) MapQualifiers (pQualSet, pQualSet2); WRITENL WRITEBSTR(OLESTR("")) } else if (CIM_OBJECT == (cimtype & ~CIM_FLAG_ARRAY)) { WRITEBSTR(OLESTR("")) WRITENL // Map the qualifiers of the parameter if (pQualSet || pQualSet2) MapQualifiers (pQualSet, pQualSet2); WRITENL WRITEBSTR(OLESTR("")) } else { WRITEBSTR(OLESTR("")) WRITENL // Map the qualifiers of the parameter if (pQualSet || pQualSet2) MapQualifiers (pQualSet, pQualSet2); WRITENL WRITEBSTR(OLESTR("")) } } else if (cimtype == CIM_REFERENCE) { // Map the reference parameter WRITEBSTR(OLESTR("")) WRITENL // Map the qualifiers of the parameter if (pQualSet || pQualSet2) MapQualifiers (pQualSet, pQualSet2); WRITENL WRITEBSTR(OLESTR("")) } else if (cimtype == CIM_OBJECT) { WRITEBSTR(OLESTR("")) WRITENL // Map the qualifiers of the parameter if (pQualSet || pQualSet2) MapQualifiers (pQualSet, pQualSet2); WRITENL WRITEBSTR(OLESTR("")) } else { // Vanilla parameter WRITEBSTR(OLESTR("")) WRITENL // Map the qualifiers of the parameter if (pQualSet || pQualSet2) MapQualifiers (pQualSet, pQualSet2); WRITENL WRITEBSTR(OLESTR("")) } WRITENL } } void CWmiToXml::MapByteValue (unsigned char val) { OLECHAR wStr[32]; swprintf (wStr, L"%d", val); WRITEBSTR(wStr) } void CWmiToXml::MapLongValue (long val) { OLECHAR wStr[32]; swprintf (wStr, L"%d", val); WRITEBSTR(wStr) } void CWmiToXml::MapShortValue (short val) { OLECHAR wStr[32]; swprintf (wStr, L"%d", val); WRITEBSTR(wStr) } void CWmiToXml::MapDoubleValue (double val) { OLECHAR floatStr [64]; swprintf (floatStr, L"%G", val); WRITEBSTR(floatStr) } void CWmiToXml::MapFloatValue (float val) { OLECHAR floatStr [64]; swprintf (floatStr, L"%G", val); WRITEBSTR(floatStr) } void CWmiToXml::MapCharValue (long val) { OLECHAR charStr [2]; swprintf (charStr, L"%c", val); WRITEBSTR(charStr) } void CWmiToXml::MapBoolValue (bool val) { if (true == val) WRITEBSTR(OLESTR("TRUE")) else WRITEBSTR(OLESTR("FALSE")) } void CWmiToXml::MapStringValue (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; WCHAR *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"<&>"); WCHAR *pStr = 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 && (0 < 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 // // ]]> -> ]]> WCHAR *pStr = 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 && (0 < wcslen (pStr))) WRITEWSTR(pStr) } else { // Just write the value WRITEBSTR(val) } } void CWmiToXml::MapReturnParameter(BSTR strParameterName, VARIANT &variant) { // Could be a PARAMETER or PARAMETER.ARRAY if(variant.vt & VT_ARRAY) WRITEBSTR(OLESTR("")); // Convert the property value to XML MapValue(variant); if(variant.vt & VT_ARRAY) WRITEBSTR(OLESTR("")) else WRITEBSTR(OLESTR("")) } // Returns the host name on both Win9x and NT platforms in Unicode form LPWSTR CWmiToXml::GetHostName() { LPWSTR pszRetValue = NULL; TCHAR pszHostName[200]; DWORD dwLength = 199; if(GetComputerName(pszHostName, &dwLength)) { #ifdef UNICODE pszRetValue = new WCHAR[dwLength + 1]; wcscpy(pszRetValue, pszHostName); #else // Convert to Wide characters if(dwLength = mbstowcs(NULL, pszHostName, 0)) { pszRetValue = new WCHAR[dwLength + 1]; mbstowcs(pszRetValue, pszHostName, dwLength); pszRetValue[dwLength] = NULL; } #endif } return pszRetValue; } BSTR CWmiToXml::GetNamespace(IWbemClassObject *pObject) { HRESULT hr = WBEM_E_FAILED; BSTR retVal = NULL; // Get the __PATH of the object VARIANT var; VariantInit (&var); if (WBEM_S_NO_ERROR == pObject->Get(L"__NAMESPACE", 0, &var, NULL, NULL)) { retVal = SysAllocString(var.bstrVal); VariantClear(&var); } return retVal; }