344 lines
9.4 KiB
C++
344 lines
9.4 KiB
C++
#include "precomp.h"
|
|
#include <objsafe.h>
|
|
#include <wbemcli.h>
|
|
#include <wmiutils.h>
|
|
#include <wbemdisp.h>
|
|
#include <xmlparser.h>
|
|
#include <genlex.h>
|
|
#include <opathlex.h>
|
|
#include <objpath.h>
|
|
|
|
#include "wmiconv.h"
|
|
#include "wmi2xml.h"
|
|
#include "classfac.h"
|
|
#include "xmltrnsf.h"
|
|
#include "XMLTransportClientHelper.h"
|
|
#include "XMLClientPacket.h"
|
|
#include "XMLClientPacketFactory.h"
|
|
#include "HTTPConnectionAgent.h"
|
|
#include "httpops.h"
|
|
#include "dcomops.h"
|
|
#include "myStream.h"
|
|
#include "MyPendingStream.h"
|
|
#include "nodefact.h"
|
|
#include "disphlp.h"
|
|
#include "docset.h"
|
|
#include "putfact.h"
|
|
#include "parse.h"
|
|
#include "dispi.h"
|
|
#include "helper.h"
|
|
#include "urlparser.h"
|
|
|
|
static HRESULT MapObjectNameToXML(IWbemXMLConvertor *pConvertor, IWbemClassObject *pObject, IStream *pStream);
|
|
|
|
// In this we are given an IWbemClassObject and are required to
|
|
// get its XML representation based on the filters like
|
|
HRESULT PackageDCOMOutput(IWbemClassObject *pObject, IXMLDOMDocument **ppXMLDocument,
|
|
WmiXMLEncoding iEncoding, VARIANT_BOOL bQualifierFilter, VARIANT_BOOL bClassOriginFilter,
|
|
VARIANT_BOOL bLocalOnly,
|
|
bool bNamesOnly)
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
*ppXMLDocument = NULL;
|
|
|
|
// RAJESHR Load the correct component based on the value of iEncoding here
|
|
IWbemXMLConvertor *pConvertor = NULL;
|
|
if(SUCCEEDED(hr = CreateXMLTranslator(&pConvertor)))
|
|
{
|
|
// Create an IWbemContext object with the appropriate flags used for
|
|
// the translation
|
|
IWbemContext *pConvertorContext = NULL;
|
|
if(SUCCEEDED(hr = CreateFlagsContext(&pConvertorContext,
|
|
(bQualifierFilter == VARIANT_TRUE)? TRUE:FALSE,
|
|
(bClassOriginFilter == VARIANT_TRUE)? TRUE:FALSE,
|
|
(bLocalOnly == VARIANT_TRUE)? TRUE:FALSE)))
|
|
{
|
|
// Create a stream for placing thr translated data
|
|
IStream *pStream = NULL;
|
|
if (SUCCEEDED(hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream)))
|
|
{
|
|
// Do the translation
|
|
if(bNamesOnly)
|
|
hr = MapObjectNameToXML(pConvertor, pObject, pStream);
|
|
else
|
|
hr = pConvertor->MapObjectToXML(pObject, NULL, 0, pConvertorContext, pStream, NULL);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// Pack the stream into an IXMLDOMDocument
|
|
if(SUCCEEDED(hr = CreateXMLDocument(ppXMLDocument)))
|
|
{
|
|
// Convert the WCHAR IStream to UTF-8
|
|
BSTR strUTF8 = NULL;
|
|
if(SUCCEEDED(hr = SaveLPWSTRStreamAsBSTR(pStream, &strUTF8)))
|
|
{
|
|
VARIANT_BOOL bResult = VARIANT_TRUE;
|
|
if(SUCCEEDED(hr = (*ppXMLDocument)->loadXML(strUTF8, &bResult)))
|
|
{
|
|
if(bResult != VARIANT_TRUE)
|
|
{
|
|
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);
|
|
}
|
|
hr = WBEM_E_INVALID_SYNTAX;
|
|
|
|
}
|
|
}
|
|
SysFreeString(strUTF8);
|
|
}
|
|
}
|
|
}
|
|
pStream->Release();
|
|
}
|
|
}
|
|
pConvertor->Release();
|
|
}
|
|
|
|
// Deallocate the out argument of the function is all didnt go well
|
|
if(FAILED(hr))
|
|
{
|
|
(*ppXMLDocument)->Release();
|
|
*ppXMLDocument = NULL;
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
// Creates an IWbemCOntext object with the correct context values required for
|
|
// conversion of WMI objects to XML for this specific operation
|
|
HRESULT CreateFlagsContext(IWbemContext **ppContext,
|
|
BOOL bIncludeQualifiers, BOOL bLocalOnly, BOOL bIncludeClassOrigin)
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
// Create an IWbemContext object
|
|
if(SUCCEEDED(hr = CoCreateInstance(CLSID_WbemContext,
|
|
0,
|
|
CLSCTX_INPROC_SERVER,
|
|
IID_IWbemContext, (LPVOID *) ppContext)))
|
|
{
|
|
if(SUCCEEDED(hr = SetBoolProperty(*ppContext, L"IncludeQualifiers", bIncludeQualifiers)) &&
|
|
SUCCEEDED(hr = SetBoolProperty(*ppContext, L"IncludeClassOrigin", bIncludeClassOrigin)) &&
|
|
SUCCEEDED(hr = SetBoolProperty(*ppContext, L"LocalOnly", bLocalOnly)) &&
|
|
SUCCEEDED(hr = SetBoolProperty(*ppContext, L"AllowWMIExtensions", TRUE)))
|
|
{
|
|
}
|
|
}
|
|
|
|
if(FAILED(hr))
|
|
(*ppContext)->Release();
|
|
return hr;
|
|
}
|
|
|
|
// A Helper function for setting a booles value in a context
|
|
HRESULT SetBoolProperty(IWbemContext *pContext, LPCWSTR pszName, BOOL bValue)
|
|
{
|
|
HRESULT result = E_FAIL;
|
|
VARIANT vValue;
|
|
VariantInit(&vValue);
|
|
vValue.vt = VT_BOOL;
|
|
if(bValue)
|
|
vValue.boolVal = VARIANT_TRUE;
|
|
else
|
|
vValue.boolVal = VARIANT_FALSE;
|
|
|
|
result = pContext->SetValue(pszName, 0, &vValue);
|
|
VariantClear(&vValue);
|
|
return result;
|
|
}
|
|
|
|
|
|
// RAJESHR - Remove this to read the GUID frm the registry on startup
|
|
DEFINE_GUID(CLSID_WbemXMLConvertor,
|
|
0x610037ec, 0xce06, 0x11d3, 0x93, 0xfc, 0x0, 0x80, 0x5f, 0x85, 0x37, 0x71);
|
|
|
|
HRESULT CreateXMLTranslator(IWbemXMLConvertor **pConvertor)
|
|
{
|
|
|
|
HRESULT result = E_FAIL;
|
|
|
|
// Create the XMLAdaptor object
|
|
//******************************************************
|
|
*pConvertor = NULL;
|
|
if(SUCCEEDED(result = CoCreateInstance(CLSID_WbemXMLConvertor,
|
|
0,
|
|
CLSCTX_INPROC_SERVER,
|
|
IID_IWbemXMLConvertor, (LPVOID *) pConvertor)))
|
|
{
|
|
}
|
|
return result;
|
|
}
|
|
|
|
|
|
DEFINE_GUID(IID_ISWbemInternalContext,
|
|
0x61EA8DBC, 0x37B8, 0x11d2, 0x8B, 0x3C, 0x0, 0x60, 0x08, 0x06, 0xD9, 0xB6);
|
|
HRESULT GetIWbemContext(IDispatch *pSet, IWbemContext **ppContext)
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
ISWbemInternalContext *pInt = NULL;
|
|
if(SUCCEEDED(hr = pSet->QueryInterface(IID_ISWbemInternalContext, (LPVOID *)&pInt)))
|
|
{
|
|
hr = pInt->GetIWbemContext(ppContext);
|
|
pInt->Release();
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
HRESULT ParseObjectPath(LPCWSTR pszObjectPath, LPWSTR *pszHostName, LPWSTR *pszNamespace, LPWSTR *pszObjectName, bool& bIsClass, bool &bIsHTTP, bool&bIsNovaPath)
|
|
{
|
|
bIsHTTP = false;
|
|
HRESULT hr = S_OK;
|
|
CURLParser theParser;
|
|
if(FAILED(hr = theParser.Initialize(pszObjectPath)))
|
|
return hr;
|
|
bIsNovaPath = theParser.IsNovapath();
|
|
|
|
LPWSTR pszTemp = NULL;
|
|
if(FAILED(hr = theParser.GetServername(&pszTemp)))
|
|
return hr;
|
|
else
|
|
{
|
|
// In case of HTTP style paths, remove the rectangular brackets
|
|
if(pszTemp && (pszTemp[0] == L'[') )
|
|
{
|
|
*pszHostName = NULL;
|
|
DWORD dwLen = wcslen(pszTemp);
|
|
if(*pszHostName = new WCHAR [dwLen-1])
|
|
{
|
|
wcsncpy(*pszHostName, pszTemp+1, dwLen-2);
|
|
(*pszHostName)[dwLen-2] = NULL;
|
|
bIsHTTP = true;
|
|
}
|
|
else
|
|
{
|
|
delete [] pszTemp;
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
// We dont need the server name any more, since we made a copy
|
|
delete [] pszTemp;
|
|
}
|
|
else // It is DCOM, we dont need to mess with the host name
|
|
*pszHostName = pszTemp;
|
|
}
|
|
// Next get the namespace
|
|
if(FAILED(hr = theParser.GetNamespace(pszNamespace)))
|
|
{
|
|
delete [] (*pszHostName);
|
|
return hr;
|
|
}
|
|
// Next get the object name
|
|
if(theParser.IsClass() || theParser.IsInstance())
|
|
{
|
|
bIsClass = false;
|
|
if(theParser.IsClass())
|
|
bIsClass = true;
|
|
if(FAILED(hr = theParser.GetObjectName(pszObjectName)))
|
|
{
|
|
delete [] (*pszHostName);
|
|
delete [] (*pszNamespace);
|
|
return hr;
|
|
}
|
|
}
|
|
|
|
// A small workaround for how the object path parser handles things
|
|
// If the objectpath happens to be "root", then the parser returns NULL
|
|
// as the namespace and "root" as the object name. This is not what we want
|
|
// when someone wants to enumerate all the classes in the namespace root
|
|
if(*pszObjectName && _wcsicmp(*pszObjectName, L"root") == 0)
|
|
{
|
|
delete [] *pszNamespace;
|
|
*pszNamespace = *pszObjectName;
|
|
*pszObjectName = NULL;
|
|
bIsNovaPath = true;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
HRESULT SaveLPWSTRStreamAsBSTR (IStream *pStream, BSTR *pstr)
|
|
{
|
|
HRESULT result = E_FAIL;
|
|
|
|
LARGE_INTEGER offset;
|
|
offset.LowPart = offset.HighPart = 0;
|
|
if(SUCCEEDED(result = pStream->Seek (offset, STREAM_SEEK_SET, NULL)))
|
|
{
|
|
// Get the LPWSTR data from the stream first
|
|
//=========================================
|
|
STATSTG statstg;
|
|
if (SUCCEEDED(result = pStream->Stat(&statstg, STATFLAG_NONAME)))
|
|
{
|
|
ULONG cbSize = (statstg.cbSize).LowPart;
|
|
WCHAR *pText = NULL;
|
|
|
|
if(cbSize)
|
|
{
|
|
if(pText = new WCHAR [(cbSize/2)])
|
|
{
|
|
if (SUCCEEDED(result = pStream->Read(pText, cbSize, NULL)))
|
|
{
|
|
// Convert the LPWSTR tp a BSTR
|
|
*pstr = NULL;
|
|
if(!(*pstr = SysAllocStringLen(pText, cbSize/2)))
|
|
result = E_OUTOFMEMORY;
|
|
}
|
|
delete [] pText;
|
|
}
|
|
else
|
|
result = E_OUTOFMEMORY;
|
|
}
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
HRESULT MapObjectNameToXML(IWbemXMLConvertor *pConvertor, IWbemClassObject *pObject, IStream *pStream)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
// Get the Genus of the object
|
|
VARIANT var;
|
|
VariantInit(&var);
|
|
if(SUCCEEDED(hr = pObject->Get(L"__GENUS", 0, &var, NULL, NULL)))
|
|
{
|
|
VARIANT nameVar;
|
|
VariantInit(&nameVar);
|
|
|
|
// Class
|
|
if(var.iVal == 1)
|
|
{
|
|
// Get its __CLASS Property
|
|
if(SUCCEEDED(hr = pObject->Get(L"__CLASS", 0, &var, NULL, NULL)))
|
|
hr = pConvertor->MapClassNameToXML(var.bstrVal, NULL, pStream);
|
|
}
|
|
else // Instance
|
|
{
|
|
// Get its __CLASS Property
|
|
if(SUCCEEDED(hr = pObject->Get(L"__RELPATH", 0, &var, NULL, NULL)))
|
|
hr = pConvertor->MapInstanceNameToXML(var.bstrVal, NULL, pStream);
|
|
}
|
|
VariantClear(&nameVar);
|
|
|
|
VariantClear(&var);
|
|
}
|
|
return hr;
|
|
}
|