#include "XMLTransportClientHelper.h" // These are globals used by the library and need to be initialized // by a call to InitWMIXMLClientLibrary and deallocated by a call // to UninitWMIXMLClientLibrary BSTR WMI_XML_STR_IRETURN_VALUE = NULL; BSTR WMI_XML_STR_NAME = NULL; BSTR WMI_XML_STR_CODE = NULL; BSTR WMI_XML_STR_ERROR = NULL; BSTR WMI_XML_STR_VALUE = NULL; // The 3 commonly used IWbemContext objects IWbemContext *g_pLocalCtx = NULL; IWbemContext *g_pNamedCtx = NULL; IWbemContext *g_pAnonymousCtx = NULL; IXMLWbemConvertor *g_pXMLWbemConvertor = NULL; ////////////////////////////////////////////////////////////////////////// // Utility functions ////////////////////////////////////////////////////////////////////////// void FreeString(WCHAR *&Str) { delete [] Str; Str = NULL; } //This was originally a macro... void RESET(WCHAR *&X) { delete [] X; X = NULL; } //This was originally a macro... void RESET(LPBYTE &X) { delete [] X; X = NULL; } HRESULT AssignString(WCHAR ** ppszTo, const WCHAR * pszFrom) { if(ppszTo == NULL || ((*ppszTo == pszFrom)&&(NULL != pszFrom))) //avoid self assignment return E_INVALIDARG; // Just assign a NULL is the source is NULL if(!pszFrom) { *ppszTo = NULL; return S_OK; } // Now, you've to copy the contents int iLen = wcslen(pszFrom) + 1; *ppszTo = NULL; if(*ppszTo = new WCHAR[iLen]) wcscpy((WCHAR *)*ppszTo,pszFrom); else return E_OUTOFMEMORY; return S_OK; } // Converts LPWSTR to its UTF-8 encoding // Returns 0 if it fails // DWORD ConvertLPWSTRToUTF8(LPCWSTR theWcharString, ULONG lNumberOfWideChars, LPSTR * lppszRetValue) { // Find the length of the Ansi string required DWORD dwBytesToWrite = WideCharToMultiByte( CP_UTF8, // UTF-8 code page 0, // performance and mapping flags theWcharString, // address of wide-character string lNumberOfWideChars, // number of characters in string NULL, // address of buffer for new string 0, // size of buffer NULL, // address of default for unmappable // characters NULL); // address of flag set when default char. used if(dwBytesToWrite == 0 ) return dwBytesToWrite; // Allocate the required length for the Ansi string *lppszRetValue = NULL; if(!(*lppszRetValue = new char[dwBytesToWrite])) return 0; // Convert BSTR to ANSI dwBytesToWrite = WideCharToMultiByte( CP_UTF8, // code page 0, // performance and mapping flags theWcharString, // address of wide-character string lNumberOfWideChars, // number of characters in string *lppszRetValue, // address of buffer for new string dwBytesToWrite, // size of buffer NULL, // address of default for unmappable // characters NULL // address of flag set when default // char. used ); return dwBytesToWrite; } // Copies the contents of a BSTR on to a LPWSTR HRESULT AssignBSTRtoWCHAR(LPWSTR *ppwszTo, BSTR strBstring) { *ppwszTo = NULL; if(SysStringLen(strBstring) > 0) { UINT iBstrLen = SysStringLen(strBstring)+1; *ppwszTo = NULL; *ppwszTo = new WCHAR[iBstrLen]; if(NULL == *ppwszTo) return E_OUTOFMEMORY; int totalBytes = (iBstrLen-1)*sizeof(WCHAR); memcpy((void *)(*ppwszTo), strBstring, totalBytes);//last one for null char memset((void *)((*ppwszTo)+iBstrLen-1), 0, sizeof(WCHAR)); // Set the last NULL character } return S_OK; } UINT ConvertMSLocaleStringToUint(LPWSTR pwszLocale) { // Locale is of the form MS_XXX, where XXX are hexadecimal characters // Our job is to convert the XXX in this string to an UINT //===================================================================================== // Assume US English as default UINT num = 0x409; // See if the string has enough characters if(NULL == pwszLocale || wcslen(pwszLocale) != 6) return num; // Covert the XXX string to a number // Temporarily modify the string to get it in the format required by wcstoul(), // Which is 0xNNN WCHAR char2 = pwszLocale[1]; WCHAR char3 = pwszLocale[2]; LPWSTR pszDummy = NULL; pwszLocale[1] = L'0'; pwszLocale[2] = L'X'; // Try to convert it if(!(num = wcstoul(pwszLocale+1, &pszDummy, 16))) num = 0x409; // Restore the contents of the original locale string pwszLocale[1] = char2; pwszLocale[2] = char3; return num; } void Get4DigitRandom(UINT *puRand) { *puRand = rand(); (*puRand) &= 9999; } void Get2DigitRandom(UINT *puRand) { *puRand = rand(); (*puRand) &= 99; } HRESULT GetBstrAttribute(IXMLDOMNode *pNode, const BSTR strAttributeName, BSTR *pstrAttributeValue) { HRESULT result = E_FAIL; *pstrAttributeValue = NULL; IXMLDOMNamedNodeMap *pNameMap = NULL; if(SUCCEEDED(result = pNode->get_attributes(&pNameMap))) { IXMLDOMNode *pAttribute = NULL; if(SUCCEEDED(result = pNameMap->getNamedItem(strAttributeName, &pAttribute))) { if(result == S_FALSE) { result = E_FAIL; } else { result = pAttribute->get_text(pstrAttributeValue); } } pAttribute->Release(); } pNameMap->Release(); return result; } HRESULT MapCimErrToWbemErr(DWORD dwCimErrCode,HRESULT *pWbemErrCode) { static DWORD dwWbemErrCodes[18]= { WBEM_NO_ERROR, WBEM_E_FAILED, WBEM_E_ACCESS_DENIED, WBEM_E_INVALID_NAMESPACE, WBEM_E_INVALID_PARAMETER, WBEM_E_INVALID_CLASS, WBEM_E_NOT_FOUND, WBEM_E_NOT_SUPPORTED, WBEM_E_CLASS_HAS_CHILDREN, WBEM_E_CLASS_HAS_INSTANCES, WBEM_E_INVALID_SUPERCLASS, WBEM_E_ALREADY_EXISTS, WBEM_E_INVALID_PROPERTY, WBEM_E_TYPE_MISMATCH, WBEM_E_INVALID_QUERY_TYPE, WBEM_E_INVALID_QUERY, WBEM_E_INVALID_METHOD, WBEM_E_INVALID_METHOD }; if(dwCimErrCode > 17) { *pWbemErrCode = WBEM_E_FAILED; return E_INVALIDARG; } *pWbemErrCode = dwWbemErrCodes[dwCimErrCode]; return S_OK; } // RAJESHR - Is this a reasonable mapping from HTTP status to WMI Errors? HRESULT MapHttpErrtoWbemErr(DWORD dwResultStatus) { HRESULT hr = WBEM_E_TRANSPORT_FAILURE; if(200 == dwResultStatus) //the caller needs to do more processing. return COM ok.. hr = S_OK; switch(dwResultStatus) { case 400: hr = WBEM_E_INVALID_PARAMETER; break; case 401: case 403: hr = WBEM_E_ACCESS_DENIED; break; case 404: case 405: case 406: case 503: hr = WBEM_E_NOT_FOUND; break; case 407: hr = WBEM_E_ACCESS_DENIED; break; case 501: hr = WBEM_E_NOT_SUPPORTED; break; } return hr; } // Takes an XML Response packet form a server and determines if this contains an ERROR element // If so, it takes the CODE value from it and maps the CIM error code to a WMI Error code HRESULT ParseXMLResponsePacket(IStream *pXMLPacket, IXMLDOMDocument **ppDoc, HRESULT *phErrCode) { if((NULL == phErrCode) || (NULL == ppDoc) || (NULL == pXMLPacket)) return E_INVALIDARG; HRESULT hr = S_OK; *ppDoc = NULL; *phErrCode = WBEM_NO_ERROR; // Parse the XML Response // Pack up the IStream in a variant and feed it to the IXMLDOMDocument object VARIANT_BOOL vbResult = VARIANT_TRUE; if(SUCCEEDED(hr = CreateXMLDocumentFromStream(ppDoc, pXMLPacket, vbResult))) { if(vbResult == VARIANT_TRUE) { IXMLDOMNodeList *pNodeList = NULL; // See if there is an ERROR element if(SUCCEEDED((*ppDoc)->getElementsByTagName(WMI_XML_STR_ERROR,&pNodeList)) && pNodeList) { IXMLDOMNode *pErrNode = NULL; if(SUCCEEDED(pNodeList->nextNode(&pErrNode))&&pErrNode) { // Get the CODE attribute of the ERROR element and map it to WMI BSTR strErrCode = NULL; if(SUCCEEDED(GetBstrAttribute(pErrNode, WMI_XML_STR_CODE, &strErrCode))) { MapCimErrToWbemErr(_wtol(strErrCode),phErrCode); SysFreeString(strErrCode); } pErrNode->Release(); } pNodeList->Release(); } } else { hr = E_FAIL; // RAJESHR - Send an HTTP error back to the client? IXMLDOMParseError *pError = NULL; if(SUCCEEDED((*ppDoc)->get_parseError(&pError))) { LONG errorCode = 0; pError->get_errorCode(&errorCode); LONG line=0, linepos=0; BSTR reason=NULL, srcText = NULL; if(SUCCEEDED(pError->get_line(&line)) && SUCCEEDED(pError->get_linepos(&linepos)) && SUCCEEDED(pError->get_reason(&reason)) && SUCCEEDED(pError->get_srcText(&srcText))) { } pError->Release(); if(reason) SysFreeString(reason); if(srcText) SysFreeString(srcText); } } } if(FAILED(hr) && (*ppDoc)) { (*ppDoc)->Release(); (*ppDoc) = NULL; } return hr; } HRESULT EncodeResponseIntoStream(LPBYTE pszXML, DWORD dwSize, VARIANT *pVariant) { HRESULT result = E_FAIL; IStream *pStream = NULL; // Create a Stream if (SUCCEEDED(result = CreateStreamOnHGlobal(NULL, TRUE, &pStream))) { // Fill it with Data if(SUCCEEDED(result = pStream->Write(pszXML, dwSize, NULL))) { LARGE_INTEGER offset; offset.LowPart = offset.HighPart = 0; pStream->Seek (offset, STREAM_SEEK_SET, NULL); // Put the stream in the variant VariantInit(pVariant); pVariant->vt = VT_UNKNOWN; pVariant->punkVal = pStream; } else pStream->Release (); } return result; } // Checks the WMI Context object to see if the special field for // dedicated enumeration has been turned on bool IsEnumtypeDedicated(IWbemContext *pCtx) { if(NULL == pCtx) return false; // We really check to see the presence of the context property rather than // check for correctness bool bResult = false; VARIANT var; VariantInit(&var); if(SUCCEEDED(pCtx->GetValue(DEDICATEDENUMPROPERTY,0,&var))) bResult = true; VariantClear(&var); return bResult; } // Removes those context values that should not be sent to the server // These are context values for client side processing HRESULT FilterContext(IWbemContext *pCtx,IWbemContext **ppFilteredCtx) { if(NULL == ppFilteredCtx) return E_INVALIDARG; if(NULL == pCtx) { *ppFilteredCtx = NULL; return S_OK; } HRESULT hr = S_OK; hr = pCtx->Clone(ppFilteredCtx); if(!SUCCEEDED(hr)) return hr; //these properties are NOT guaranteed to exist in the context object.. //we wont fail if any of these deltes fail. (*ppFilteredCtx)->DeleteValue(DEDICATEDENUMPROPERTY,0); (*ppFilteredCtx)->DeleteValue(PROXYNAMEPROPERTY,0); (*ppFilteredCtx)->DeleteValue(PROXYBYPASSPROPERTY,0); return hr; } // This is a function that reads the data form an IStream and returns it. // It assumes that the data is actually a stream of WCHARs and hence // returns the size as number of WCHARs rather than the number of bytes read from the IStream HRESULT GetWStringFromStream(IStream *pStream, WCHAR **ppwszBody,DWORD *pdwLengthofPacket) { HRESULT hr = S_OK; STATSTG stat; memset(&stat,0,sizeof(STATSTG)); LARGE_INTEGER offset; offset.LowPart = offset.HighPart = 0; pStream->Seek (offset, STREAM_SEEK_SET, NULL); pStream->Stat(&stat,1); unsigned int iLen = (unsigned int)stat.cbSize.LowPart; *ppwszBody = NULL; if(*ppwszBody = new WCHAR[(iLen/2) +1]) //size is in BYTEs. we want WCHARs { hr = pStream->Read((void*)*ppwszBody, iLen, pdwLengthofPacket); *pdwLengthofPacket = (*pdwLengthofPacket)/2; } else hr = E_OUTOFMEMORY; return hr; } HRESULT ConvertContextObjectToXMLStream(IStream *pStream, IWbemContext *pCtx) { if((NULL == pCtx)||(NULL == pStream)) return E_INVALIDARG; //RAJESHR : Add code to convert context to string using interface RAjesh will create... HRESULT hr = S_OK; return hr; } // Gets Proxy information from the fields in IWbemContext HRESULT GetProxyInformation(IWbemContext *pCtx, WCHAR **ppwszProxyName, WCHAR **ppwszProxyBypass) { if((NULL == ppwszProxyName)||(NULL == ppwszProxyBypass)||(pCtx==NULL)) return E_INVALIDARG; *ppwszProxyName = *ppwszProxyBypass = NULL; HRESULT hr = WBEM_S_NO_ERROR; VARIANT var; VariantInit(&var); // Get the Proxy Name if(SUCCEEDED(hr = pCtx->GetValue(PROXYNAMEPROPERTY,0,&var))) { if(SUCCEEDED(hr = AssignBSTRtoWCHAR(ppwszProxyName, var.bstrVal))) { VariantInit(&var); if(SUCCEEDED(hr = pCtx->GetValue(PROXYBYPASSPROPERTY, 0, &var))) hr = AssignBSTRtoWCHAR(ppwszProxyBypass,var.bstrVal); VariantClear(&var); } VariantClear(&var); } // Delete allocated resources if the function failed if(FAILED(hr)) { delete [] *ppwszProxyName; delete [] *ppwszProxyBypass; *ppwszProxyName = *ppwszProxyBypass = NULL; } return hr; } // Unlike the previous function that mapped the ERROR value in the CIM error to WMI hResult, // this function maps the WMI error in Whistler packets to hResult HRESULT GetHresultfromXMLPacket(IStream *pPacket, HRESULT *hres) { HRESULT hr = S_OK; if((NULL == pPacket)||(NULL == hres)) return E_INVALIDARG; IXMLDOMDocument *pXMLDomDocument=NULL; VARIANT_BOOL vbResult = VARIANT_TRUE; if(SUCCEEDED(hr = CreateXMLDocumentFromStream(&pXMLDomDocument, pPacket, vbResult))) { if(vbResult == VARIANT_TRUE) { //THE CONTRACT WITH THE XMLHTTP SERVER IS THAT, FOR THE TRANSACTION OPERATIONS THAT EXPECT A HRESULT //IT WILL PACK THE RESULTING HRESULT IN THE *FIRST* VALUE TAG INSIDE THE IRETURNVALUE.. IXMLDOMNodeList *pNodeList=NULL; if(SUCCEEDED(hr = pXMLDomDocument->getElementsByTagName(WMI_XML_STR_VALUE, &pNodeList)) && pNodeList) { IXMLDOMNode *pErrNode = NULL; if(SUCCEEDED(hr = pNodeList->nextNode(&pErrNode)) && pErrNode) { BSTR strErrCode = NULL; if(SUCCEEDED(hr = pErrNode->get_text(&strErrCode))) { *hres = _wtol(strErrCode); SysFreeString(strErrCode); } pErrNode->Release(); } pNodeList->Release(); } else { // We got a badly formed response from the server hr = WBEM_E_FAILED; } } pXMLDomDocument->Release(); } return hr; } // This function gets the CLASS or INSTANCE element from inside an // IRETURNVALUE element. HRESULT Parse_IRETURNVALUE_Node(IXMLDOMNode *pXMLDomNodeTemp,IXMLDOMNode **ppXMLDomNodeChild) { if((NULL == pXMLDomNodeTemp)||(NULL == ppXMLDomNodeChild)) return E_INVALIDARG; HRESULT hr = S_OK; BSTR strNodename = NULL; if(!SUCCEEDED(hr = pXMLDomNodeTemp->get_nodeName(&strNodename))) return hr; //node contains CLASS/INSTANCE, no parsing required.. if((_wcsicmp(strNodename,L"CLASS")==0)||(_wcsicmp(strNodename,L"INSTANCE")==0) ) { *ppXMLDomNodeChild = pXMLDomNodeTemp; pXMLDomNodeTemp->AddRef(); SysFreeString(strNodename); return S_OK; } // No need to keep the name with us SysFreeString(strNodename); // The given node was not a CLASS or INSTANCE element, // In that case it must be a VALUE.NAMEDINSTANCE element // So, let's look at its children *ppXMLDomNodeChild = NULL; IXMLDOMNodeList *pXMLDomNodeList = NULL; if(SUCCEEDED(hr = pXMLDomNodeTemp->get_childNodes(&pXMLDomNodeList)) && pXMLDomNodeList) { // Get the next child bool bFoundinstance = false; IXMLDOMNode *pChild = NULL; while(SUCCEEDED(hr = pXMLDomNodeList->nextNode(&pChild)) && pChild) { // Check its name BSTR strChildName = NULL; if(SUCCEEDED(hr = pChild->get_nodeName(&strChildName))) { if(_wcsicmp(strChildName, L"INSTANCE")==0) //INSTANCE { SysFreeString(strChildName); break; } SysFreeString(strChildName); } pChild->Release(); pChild = NULL; } // Did we find one? if(pChild) { *ppXMLDomNodeChild = pChild; pChild->AddRef(); } pXMLDomNodeList->Release(); } return (*ppXMLDomNodeChild) ? S_OK : E_FAIL; } // THis initialized the 3 global variables that are IWbemContext objects for // the most commonly used IWbemContexts for the Convertor static HRESULT CreateFlagsContext() { HRESULT hres = S_OK; if(SUCCEEDED(hres = CoCreateInstance(CLSID_WbemContext,NULL,CLSCTX_INPROC,IID_IWbemContext,(LPVOID *)&g_pLocalCtx))) { VARIANT var; VariantInit(&var); var.vt = VT_BOOL; var.boolVal = VARIANT_TRUE; g_pLocalCtx->SetValue(L"AllowWMIExtensions", 0,&var); g_pLocalCtx->SetValue(L"IncludeQualifiers", 0,&var); g_pLocalCtx->SetValue(L"IncludeClassOrigin", 0,&var); g_pLocalCtx->SetValue(L"ExcludeSystemProperties", 0,&var); VariantInit(&var); var.vt = VT_I4; var.lVal = pathLevelLocal; g_pLocalCtx->SetValue(L"PathLevel", 0,&var); } if(SUCCEEDED(hres) && SUCCEEDED(hres = CoCreateInstance(CLSID_WbemContext,NULL,CLSCTX_INPROC,IID_IWbemContext,(LPVOID *)&g_pAnonymousCtx))) { VARIANT var; VariantInit(&var); var.vt = VT_BOOL; var.boolVal = VARIANT_TRUE; g_pAnonymousCtx->SetValue(L"AllowWMIExtensions", 0,&var); g_pAnonymousCtx->SetValue(L"IncludeQualifiers", 0,&var); g_pAnonymousCtx->SetValue(L"IncludeClassOrigin", 0,&var); g_pAnonymousCtx->SetValue(L"ExcludeSystemProperties", 0,&var); VariantInit(&var); var.vt = VT_I4; var.lVal = pathLevelAnonymous; g_pAnonymousCtx->SetValue(L"PathLevel", 0,&var); } if(SUCCEEDED(hres) && SUCCEEDED(hres = CoCreateInstance(CLSID_WbemContext,NULL,CLSCTX_INPROC,IID_IWbemContext,(LPVOID *)&g_pNamedCtx))) { VARIANT var; VariantInit(&var); var.vt = VT_BOOL; var.boolVal = VARIANT_TRUE; g_pNamedCtx->SetValue(L"AllowWMIExtensions", 0,&var); g_pNamedCtx->SetValue(L"IncludeQualifiers", 0,&var); g_pNamedCtx->SetValue(L"IncludeClassOrigin", 0,&var); g_pNamedCtx->SetValue(L"ExcludeSystemProperties", 0,&var); VariantInit(&var); var.vt = VT_I4; var.lVal = pathLevelNamed; g_pNamedCtx->SetValue(L"PathLevel", 0,&var); } return hres; } // {41388E26-F847-4a9d-96C0-9A847DBA4CFE} DEFINE_GUID(CLSID_XMLWbemConvertor, 0x41388e26, 0xf847, 0x4a9d, 0x96, 0xc0, 0x9a, 0x84, 0x7d, 0xba, 0x4c, 0xfe); // Initialize global variable required by the static library here HRESULT InitWMIXMLClientLibrary() { // Seed the random number library with the current time srand( (unsigned int)time(NULL) ); HRESULT hr = E_FAIL; if(SUCCEEDED(hr = CreateFlagsContext())) { if(SUCCEEDED(hr = CoCreateInstance(CLSID_XMLWbemConvertor, NULL, CLSCTX_INPROC_SERVER,IID_IXMLWbemConvertor, (void**)&g_pXMLWbemConvertor))) { WMI_XML_STR_IRETURN_VALUE = SysAllocString(L"IRETURNVALUE"); WMI_XML_STR_NAME = SysAllocString(L"NAME"); WMI_XML_STR_CODE = SysAllocString(L"CODE"); WMI_XML_STR_ERROR = SysAllocString(L"ERROR"); WMI_XML_STR_VALUE = SysAllocString(L"VALUE"); if(WMI_XML_STR_IRETURN_VALUE && WMI_XML_STR_NAME && WMI_XML_STR_CODE && WMI_XML_STR_ERROR && WMI_XML_STR_VALUE) hr = S_OK; else hr = E_OUTOFMEMORY; } } // Check if each of the initializations was a success // Else, free resources and report error // We dont want to be in a partially initialized state if(FAILED(hr)) UninitWMIXMLClientLibrary(); return hr; } // Uninitialize globals and release resources here HRESULT UninitWMIXMLClientLibrary() { SysFreeString(WMI_XML_STR_IRETURN_VALUE); SysFreeString(WMI_XML_STR_NAME); SysFreeString(WMI_XML_STR_CODE); SysFreeString(WMI_XML_STR_ERROR); SysFreeString(WMI_XML_STR_VALUE); WMI_XML_STR_IRETURN_VALUE = NULL; WMI_XML_STR_NAME = NULL; WMI_XML_STR_CODE = NULL; WMI_XML_STR_ERROR = NULL; WMI_XML_STR_VALUE = NULL; if(g_pLocalCtx) { g_pLocalCtx->Release(); g_pLocalCtx = NULL; } if(g_pNamedCtx) { g_pNamedCtx->Release(); g_pNamedCtx = NULL; } if(g_pAnonymousCtx) { g_pAnonymousCtx->Release(); g_pAnonymousCtx = NULL; } if(g_pXMLWbemConvertor) { g_pXMLWbemConvertor->Release(); g_pXMLWbemConvertor = NULL; } return S_OK; } HRESULT CreateXMLDocument(IXMLDOMDocument **ppXMLDocument) { HRESULT hr = E_FAIL; if(SUCCEEDED(hr = CoCreateInstance(CLSID_DOMDocument, NULL, CLSCTX_INPROC_SERVER, IID_IXMLDOMDocument, (LPVOID *)ppXMLDocument))) { if(SUCCEEDED(hr = (*ppXMLDocument)->put_async(VARIANT_FALSE))) { if(SUCCEEDED(hr = (*ppXMLDocument)->put_resolveExternals(VARIANT_FALSE))) { if(SUCCEEDED(hr = (*ppXMLDocument)->put_validateOnParse(VARIANT_FALSE))) { } } } // Release out argument it things didnt go well if(FAILED(hr)) { (*ppXMLDocument)->Release(); *ppXMLDocument = NULL; } } return hr; } HRESULT CreateXMLDocumentFromStream(IXMLDOMDocument **ppXMLDocument, IStream *pStream, VARIANT_BOOL &bResult) { HRESULT hr = E_FAIL; if(SUCCEEDED(hr = CreateXMLDocument(ppXMLDocument))) { VARIANT xmlVariant; VariantInit (&xmlVariant); xmlVariant.vt = VT_UNKNOWN; xmlVariant.punkVal = pStream; if(SUCCEEDED(hr = (*ppXMLDocument)->load(xmlVariant, &bResult))) { if(bResult == VARIANT_FALSE) { // This code is for debugging only IXMLDOMParseError *pError = NULL; if(SUCCEEDED((*ppXMLDocument)->get_parseError(&pError))) { LONG errorCode = 0; pError->get_errorCode(&errorCode); LONG line=0, linepos=0; BSTR reason=NULL, srcText = NULL; if(SUCCEEDED(pError->get_line(&line)) && SUCCEEDED(pError->get_linepos(&linepos)) && SUCCEEDED(pError->get_reason(&reason)) && SUCCEEDED(pError->get_srcText(&srcText))) { } pError->Release(); if(reason) SysFreeString(reason); if(srcText) SysFreeString(srcText); pError->Release(); } } } else { (*ppXMLDocument)->Release(); *ppXMLDocument = NULL; } // No need to clear the variant since we did not addref() the stream } return hr; } /* THESE ARE NOT BEING USED CURRENTLY HRESULT CXMLClientPacket::ConvertContextObjectToXMLString(WCHAR **ppwszXMLString, DWORD *pdwDataLength) { HRESULT hr = S_OK; //aborting the attempt to rewrite this function as Rajesh has decided //to create an interface that would provide this functionality.. //RAJESHR: use Rajesh's interface when ready... if((NULL == m_pCtx)||(NULL == ppwszXMLString)) return E_INVALIDARG; IStream *pStream=NULL; if(SUCCEEDED(hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream))) { WRITETOSTREAM(pStream,L"\r\n"); if(SUCCEEDED(m_pCtx->BeginEnumeration(0))) { VARIANT vNextArgValue; VariantInit(&vNextArgValue); BSTR strNextArgName = NULL; while(m_pCtx->Next(0, &strNextArgName, &vNextArgValue) != WBEM_S_NO_MORE_DATA) { //process each property of the context and fill in the XML equivalent //into the IStream pointer.. hr=ProcessContextProperty(strNextArgName,vNextArgValue,pStream); SysFreeString(strNextArgName); strNextArgName = NULL; VariantInit(&vNextArgValue); if(!SUCCEEDED(hr)) break; } VariantClear(&vNextArgValue); } WRITETOSTREAM(pStream,L"\r\n"); } RELEASE_AND_NULL_INTERFACE(pStream); return hr; } HRESULT CXMLClientPacket::ProcessContextProperty(BSTR &strNextArgName, VARIANT &vNextArgValue, IStream *pStream) { HRESULT hr = S_OK; if((NULL != strNextArgName)&&(NULL != pStream)) { if(vNextArgValue.vt^VT_ARRAY) { //this is not an ARRAY, just a single property if(!(vNextArgValue.vt^VT_UNKNOWN)) //this property contains an Object. { WRITETOSTREAM(pStream,L""); hr = ProcessSingleContextProperty(strNextArgName,vNextArgValue,pStream); WRITETOSTREAM(pStream,L""); } else { WRITETOSTREAM(pStream,L""); hr = ProcessSingleContextProperty(strNextArgName,vNextArgValue,pStream); WRITETOSTREAM(pStream,L""); } } else { //this is an ARRAY of properties hr = ProcessArrayContextProperty(strNextArgName,vNextArgValue,pStream); } } return hr; } HRESULT CXMLClientPacket::ProcessSingleContextProperty(BSTR &strNextArgName,VARIANT &vNextArgValue, IStream *pStream) { //NO NULL CHECKS NECESSARY. CONTROL WONT REACH HERE WITH NULLS HRESULT hr = S_OK; if(!(vNextArgValue.vt^VT_UNKNOWN)) //this property contains an Object. { WRITETOSTREAM(pStream,L""); //RAJESHR: CODE TO GET CONVERTOR INTERFACE FROM SINGLETON CLASS AND DO A MAPOBJECTTOXML.. WRITETOSTREAM(pStream,L""); } else { WRITETOSTREAM(pStream,L""); //VT TYPES TAKEN FROM CIM DTD DEFINITION OF VTTYPE //VT_UNKNOWN IS HANDLED SEPARATELY ABOVE.. switch(vNextArgValue.vt) { case VT_I4: { WCHAR tmp[32]; //VT_I4 number has to fit in this easily tmp[0] = '\0'; wsprintf(tmp,L"%u\0",vNextArgValue.lVal); WRITETOSTREAM(pStream,tmp); break; } case VT_R8: { WCHAR tmp[32]; //VT_I4 number has to fit in this easily tmp[0] = '\0'; wsprintf(tmp,L"%f\0",vNextArgValue.fltVal); WRITETOSTREAM(pStream,tmp); break; } case VT_BOOL: { if(vNextArgValue.boolVal == VARIANT_TRUE) { WRITETOSTREAM(pStream,L"TRUE"); } else { WRITETOSTREAM(pStream,L"FALSE"); } break; } case VT_BSTR: { WRITETOSTREAM(pStream,vNextArgValue.bstrVal); break; } } WRITETOSTREAM(pStream,L""); } return hr; } HRESULT CXMLClientPacket::ProcessArrayContextProperty(BSTR &strNextArgName,VARIANT &vNextArgValue, IStream *pStream) { //NO NULL CHECKS NECESSARY. CONTROL WONT REACH HERE WITH NULLS HRESULT hr = S_OK; //RAJESHR: ADD BODY. USE PREVIOUS FN IN A LOOP.. return hr; } HRESULT GetVTType(VARIANT &var,IStream *pStream) { HRESULT hr = S_OK; if(NULL == pStream) hr = E_INVALIDARG; else { WRITETOSTREAM(pStream,L"\""); switch(var.vt) { case VT_I4: WRITETOSTREAM(pStream,L" VT_I4"); break; case VT_R8: WRITETOSTREAM(pStream,L" VT_R8"); break; case VT_BOOL: WRITETOSTREAM(pStream,L" VT_BOOL"); break; case VT_BSTR: WRITETOSTREAM(pStream,L" VT_BSTR"); break; case VT_UNKNOWN: WRITETOSTREAM(pStream,L" VT_UNKNOWN"); break; case VT_NULL: WRITETOSTREAM(pStream,L" VT_NULL"); break; default: hr = E_INVALIDARG; break; } WRITETOSTREAM(pStream,L"\""); } return hr; } */ /* HRESULT WriteSecurityObjectToStream(IWbemRawSdAccessor *pSecurityObject,IStream *pStream) { ULONG dwSize=0; HRESULT hr = S_OK; if(!SUCCEEDED(hr=pSecurityObject->Get(0,0,&dwSize,NULL))) return hr; BYTE *pSecurityInfo = new BYTE[dwSize]; if(NULL == pSecurityInfo) return E_OUTOFMEMORY; pSecurityObject->Get(0,dwSize,&dwSize,pSecurityInfo); pStream->Write(pSecurityInfo,dwSize,&dwSize); return hr; } HRESULT PlaceStringAsSecurityinfo(IWbemRawSdAccessor *pSecurityObject,const BYTE *pwszSecurityinfo,DWORD dwSize) { //pwszSecurityinfo actually contains the XML response sent by the server. //the security info is packed into an IPARAMVALUE, . HRESULT hr = S_OK; IXMLDOMDocument *pXMLDomDocument = NULL; IXMLDOMNodeList *pXMLDomNodelist = NULL; IXMLDOMNode *pXMLDomNode = NULL; VARIANT xmlVariant; VariantInit(&xmlVariant); do { hr = CoCreateInstance(CLSID_DOMDocument, NULL, CLSCTX_INPROC_SERVER,IID_IXMLDOMDocument, (void**)&pXMLDomDocument); if(!SUCCEEDED(hr)) break; if(NULL == pXMLDomDocument) { hr = E_FAIL; break; } pXMLDomDocument->put_async(VARIANT_FALSE); VARIANT_BOOL vbResult = VARIANT_TRUE; if(!SUCCEEDED(hr = EncodeResponseIntoStream((LPBYTE)pwszSecurityinfo, dwSize, &xmlVariant))) { break; } if(!SUCCEEDED(hr = pXMLDomDocument->load(xmlVariant, &vbResult))) { break; } if(vbResult != VARIANT_TRUE) { hr = E_FAIL; break; } hr = pXMLDomDocument->getElementsByTagName(WMI_XML_STR_IRETURN_VALUE,&pXMLDomNodelist); if(!SUCCEEDED(hr) || (pXMLDomNodelist==NULL)) break; if(!SUCCEEDED(hr = pXMLDomNodelist->nextNode(&pXMLDomNode))) //pNode now has IRETURNVALUE break; RELEASEINTERFACE(pXMLDomNodelist); //got the node, now dont need the node list. will reuse it if (!SUCCEEDED(pXMLDomNode->get_childNodes (&pXMLDomNodelist))) //getobjectsecurity must have returned a .. break; RELEASEINTERFACE(pXMLDomNode); while (SUCCEEDED(hr) && SUCCEEDED(pXMLDomNodelist->nextNode (&pXMLDomNode)) && pXMLDomNode) { BSTR strNodeName = NULL,strPropname=NULL; if (SUCCEEDED(pXMLDomNode->get_nodeName (&strNodeName))) { if (0 == _wcsicmp(strNodeName, L"PROPERTY")) { if(!SUCCEEDED(hr=GetBstrAttribute(pXMLDomNode, WMI_XML_STR_NAME, &strPropname))) break; if(0==_wcsicmp(strPropname,L"ppvResult")) break; } } } if(!SUCCEEDED(hr)) break; //now we have the domnode which has the security information... BSTR strSecurityinfo = NULL; if(!SUCCEEDED(hr = pXMLDomNode->get_text(&strSecurityinfo))) break; ULONG uBufsize = SysStringLen(strSecurityinfo); WCHAR *pwszSecurityinfo = NULL; //dont worry, AssignBStr.. function uses memset internally... if(!SUCCEEDED(hr = AssignBSTRtoWCHAR(&pwszSecurityinfo,strSecurityinfo))) break; SysFreeString(strSecurityinfo); hr = pSecurityObject->Put(0,uBufsize,(LPBYTE)pwszSecurityinfo); }while(0); VariantClear(&xmlVariant); RELEASEINTERFACE(pXMLDomDocument); RELEASEINTERFACE(pXMLDomNodelist); RELEASEINTERFACE(pXMLDomNode); return E_NOTIMPL; } */