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