1172 lines
30 KiB
C++
1172 lines
30 KiB
C++
#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"<CONTEXTOBJECT>\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"</CONTEXTOBJECT>\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"<CONTEXTPROPERTY.OBJECT NAME=\"");
|
|
WRITETOSTREAM(pStream,strNextArgName);
|
|
WRITETOSTREAM(pStream,L"\">");
|
|
|
|
hr = ProcessSingleContextProperty(strNextArgName,vNextArgValue,pStream);
|
|
|
|
WRITETOSTREAM(pStream,L"</CONTEXTPROPERTY.OBJECT>");
|
|
|
|
}
|
|
else
|
|
{
|
|
WRITETOSTREAM(pStream,L"<CONTEXTPROPERTY NAME=\"");
|
|
WRITETOSTREAM(pStream,strNextArgName);
|
|
WRITETOSTREAM(pStream,L" VTType=");
|
|
GetVTType(vNextArgValue,pStream);
|
|
WRITETOSTREAM(pStream,L">");
|
|
|
|
hr = ProcessSingleContextProperty(strNextArgName,vNextArgValue,pStream);
|
|
|
|
WRITETOSTREAM(pStream,L"</CONTEXTPROPERTY>");
|
|
}
|
|
|
|
}
|
|
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"<VALUE.OBJECT>");
|
|
//RAJESHR: CODE TO GET CONVERTOR INTERFACE FROM SINGLETON CLASS AND DO A MAPOBJECTTOXML..
|
|
WRITETOSTREAM(pStream,L"</VALUE.OBJECT>");
|
|
}
|
|
else
|
|
{
|
|
WRITETOSTREAM(pStream,L"<VALUE>");
|
|
|
|
//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"</VALUE>");
|
|
}
|
|
|
|
|
|
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, <VALUE></VALUE>.
|
|
|
|
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 <PROPERTY NAME=ppvResult> <VALUE>..
|
|
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;
|
|
}
|
|
*/
|
|
|