621 lines
16 KiB
C++
621 lines
16 KiB
C++
//***************************************************************************
|
|
//
|
|
// Copyright (c) 1997-1999 Microsoft Corporation
|
|
//
|
|
// WBEMXMLT.CPP
|
|
//
|
|
// alanbos 15-Aug-96 Created.
|
|
//
|
|
// Defines the implementation of IWbemXMLTranslator
|
|
//
|
|
//***************************************************************************
|
|
|
|
|
|
#include "precomp.h"
|
|
|
|
static BSTR MapHresultToWmiDescription (HRESULT hr);
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CXMLTranslator::CXMLTranslator
|
|
//
|
|
// DESCRIPTION:
|
|
//
|
|
// Constructor.
|
|
//
|
|
//***************************************************************************
|
|
|
|
CXMLTranslator::CXMLTranslator()
|
|
{
|
|
InitializeCriticalSection (&m_cs);
|
|
m_queryFormat = SysAllocString (OLESTR("WQL"));
|
|
m_bAllowWMIExtensions = VARIANT_FALSE;
|
|
m_pITINeutral = NULL;
|
|
m_schemaURL = NULL;
|
|
m_iQualifierFilter = wmiXMLFilterLocal;
|
|
m_iDTDVersion = wmiXMLDTDVersion_2_0;
|
|
m_bHostFilter = VARIANT_TRUE; // Don't filter out the host
|
|
m_bNamespaceInDeclGroup = VARIANT_FALSE;
|
|
m_iClassOriginFilter = wmiXMLClassOriginFilterNone; // No class origin info
|
|
m_iDeclGroupType = wmiXMLDeclGroup;
|
|
m_cRef=0;
|
|
m_hResult = S_OK;
|
|
InterlockedIncrement(&g_cObj);
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CXMLTranslator::~CXMLTranslator
|
|
//
|
|
// DESCRIPTION:
|
|
//
|
|
// Destructor.
|
|
//
|
|
//***************************************************************************
|
|
|
|
CXMLTranslator::~CXMLTranslator(void)
|
|
{
|
|
InterlockedDecrement(&g_cObj);
|
|
SysFreeString (m_queryFormat);
|
|
|
|
if (m_pITINeutral)
|
|
m_pITINeutral->Release ();
|
|
|
|
EnterCriticalSection (&m_cs);
|
|
if (m_schemaURL)
|
|
SysFreeString (m_schemaURL);
|
|
LeaveCriticalSection (&m_cs);
|
|
|
|
DeleteCriticalSection (&m_cs);
|
|
}
|
|
|
|
//***************************************************************************
|
|
// HRESULT CXMLTranslator::QueryInterface
|
|
// long CXMLTranslator::AddRef
|
|
// long CXMLTranslator::Release
|
|
//
|
|
// DESCRIPTION:
|
|
//
|
|
// Standard Com IUNKNOWN functions.
|
|
//
|
|
//***************************************************************************
|
|
|
|
STDMETHODIMP CXMLTranslator::QueryInterface (
|
|
|
|
IN REFIID riid,
|
|
OUT LPVOID *ppv
|
|
)
|
|
{
|
|
*ppv=NULL;
|
|
|
|
if (IID_IUnknown==riid)
|
|
*ppv = reinterpret_cast<IUnknown*>(this);
|
|
else if (IID_IWmiXMLTranslator==riid)
|
|
*ppv = (IWmiXMLTranslator *)this;
|
|
else if (IID_IDispatch==riid)
|
|
*ppv = (IDispatch *)this;
|
|
else if (IID_IObjectSafety==riid)
|
|
*ppv = (IObjectSafety *)this;
|
|
else if (IID_ISupportErrorInfo==riid)
|
|
*ppv = (ISupportErrorInfo *)this;
|
|
|
|
if (NULL!=*ppv)
|
|
{
|
|
((LPUNKNOWN)*ppv)->AddRef();
|
|
return NOERROR;
|
|
}
|
|
|
|
return ResultFromScode(E_NOINTERFACE);
|
|
}
|
|
|
|
STDMETHODIMP_(ULONG) CXMLTranslator::AddRef(void)
|
|
{
|
|
InterlockedIncrement(&m_cRef);
|
|
return m_cRef;
|
|
}
|
|
|
|
STDMETHODIMP_(ULONG) CXMLTranslator::Release(void)
|
|
{
|
|
InterlockedDecrement(&m_cRef);
|
|
if (0L!=m_cRef)
|
|
return m_cRef;
|
|
delete this;
|
|
return 0;
|
|
}
|
|
|
|
//***************************************************************************
|
|
// HRESULT CXMLTranslator::GetTypeInfoCount
|
|
// HRESULT CXMLTranslator::GetTypeInfo
|
|
// HRESULT CXMLTranslator::GetIDsOfNames
|
|
// HRESULT CXMLTranslator::Invoke
|
|
//
|
|
//
|
|
// DESCRIPTION:
|
|
//
|
|
// Standard Com IDispatch functions.
|
|
//
|
|
//***************************************************************************
|
|
|
|
STDMETHODIMP CXMLTranslator::GetTypeInfoCount(UINT *pctInfo)
|
|
{
|
|
*pctInfo = 1;
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP CXMLTranslator:: GetTypeInfo(UINT itInfo, LCID lcid,
|
|
ITypeInfo **ppITypeInfo)
|
|
{
|
|
ITypeLib *pITypeLib = NULL;
|
|
ITypeInfo **ppITI = NULL;
|
|
|
|
if (0 != itInfo)
|
|
return TYPE_E_ELEMENTNOTFOUND;
|
|
|
|
if (NULL == ppITypeInfo)
|
|
return E_POINTER;
|
|
|
|
*ppITypeInfo = NULL;
|
|
|
|
switch (PRIMARYLANGID(lcid))
|
|
{
|
|
case LANG_NEUTRAL:
|
|
case LANG_ENGLISH:
|
|
ppITI = &m_pITINeutral;
|
|
break;
|
|
|
|
default:
|
|
return DISP_E_UNKNOWNLCID;
|
|
}
|
|
|
|
if (ppITI)
|
|
{
|
|
HRESULT hr;
|
|
|
|
if (FAILED(hr = LoadRegTypeLib(LIBID_WmiXML, 1, 0,
|
|
PRIMARYLANGID(lcid), &pITypeLib)))
|
|
hr = LoadTypeLib(OLESTR("WMIXMLT.TLB"), &pITypeLib);
|
|
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
hr = pITypeLib->GetTypeInfoOfGuid (IID_IWmiXMLTranslator, ppITI);
|
|
pITypeLib->Release ();
|
|
|
|
if (FAILED(hr))
|
|
return hr;
|
|
}
|
|
|
|
// Getting here means we have a real ITypeInfo to assign
|
|
(*ppITI)->AddRef ();
|
|
*ppITypeInfo = *ppITI;
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP CXMLTranslator::GetIDsOfNames (REFIID riid,
|
|
OLECHAR **rgszNames, UINT cNames, LCID lcid, DISPID *rgDispID)
|
|
{
|
|
ITypeInfo *pTI = NULL;
|
|
|
|
if (IID_NULL != riid)
|
|
return DISP_E_UNKNOWNINTERFACE;
|
|
|
|
HRESULT hr = GetTypeInfo (0, lcid, &pTI);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
pTI->GetIDsOfNames (rgszNames, cNames, rgDispID);
|
|
pTI->Release ();
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CXMLTranslator::Invoke (DISPID dispID, REFIID riid,
|
|
LCID lcid, unsigned short wFlags, DISPPARAMS *pDispParams,
|
|
VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
|
|
{
|
|
ITypeInfo *pTI = NULL;
|
|
m_hResult = S_OK;
|
|
|
|
if (IID_NULL != riid)
|
|
return DISP_E_UNKNOWNINTERFACE;
|
|
|
|
HRESULT hr = GetTypeInfo (0, lcid, &pTI);
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
hr = pTI->Invoke (this, dispID, wFlags, pDispParams, pVarResult,
|
|
pExcepInfo, puArgErr);
|
|
|
|
pTI->Release ();
|
|
|
|
if (FAILED(m_hResult))
|
|
{
|
|
if (NULL != pExcepInfo)
|
|
{
|
|
if (pExcepInfo->bstrDescription)
|
|
SysFreeString (pExcepInfo->bstrDescription);
|
|
|
|
pExcepInfo->bstrDescription = MapHresultToWmiDescription (m_hResult);
|
|
|
|
if (pExcepInfo->bstrSource)
|
|
SysFreeString (pExcepInfo->bstrSource);
|
|
|
|
pExcepInfo->bstrSource = SysAllocString (L"XMLTranslator");
|
|
pExcepInfo->scode = m_hResult;
|
|
|
|
hr = DISP_E_EXCEPTION;
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
BSTR MapHresultToWmiDescription (HRESULT hr)
|
|
{
|
|
BSTR bsMessageText = NULL;
|
|
|
|
// Used as our error code translator
|
|
IWbemStatusCodeText *pErrorCodeTranslator = NULL;
|
|
|
|
HRESULT result = CoCreateInstance (CLSID_WbemStatusCodeText, 0, CLSCTX_INPROC_SERVER,
|
|
IID_IWbemStatusCodeText, (LPVOID *) &pErrorCodeTranslator);
|
|
|
|
if (SUCCEEDED (result))
|
|
{
|
|
HRESULT sc = pErrorCodeTranslator->GetErrorCodeText(
|
|
hr, (LCID) 0, 0, &bsMessageText);
|
|
|
|
pErrorCodeTranslator->Release ();
|
|
}
|
|
|
|
return bsMessageText;
|
|
}
|
|
|
|
//***************************************************************************
|
|
// HRESULT CXMLTranslator::get_SchemaURL
|
|
// HRESULT CXMLTranslator::put_SchemaURL
|
|
//
|
|
// DESCRIPTION:
|
|
//
|
|
// IWbemXMLTranslator methods for handling properties.
|
|
//
|
|
// Property Name Function
|
|
// SchemaURL URL to locate DTD, if required
|
|
//
|
|
//***************************************************************************
|
|
|
|
HRESULT CXMLTranslator::get_SchemaURL (BSTR *pSchemaURL)
|
|
{
|
|
if (pSchemaURL)
|
|
{
|
|
*pSchemaURL = NULL;
|
|
|
|
EnterCriticalSection (&m_cs);
|
|
if (m_schemaURL)
|
|
*pSchemaURL = SysAllocString (m_schemaURL);
|
|
LeaveCriticalSection (&m_cs);
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT CXMLTranslator::put_SchemaURL (BSTR schemaURL)
|
|
{
|
|
if (!schemaURL)
|
|
return WBEM_E_FAILED;
|
|
|
|
EnterCriticalSection (&m_cs);
|
|
if (m_schemaURL)
|
|
SysFreeString (m_schemaURL);
|
|
|
|
m_schemaURL = SysAllocString (schemaURL);
|
|
LeaveCriticalSection (&m_cs);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// 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,
|
|
BSTR *pXML
|
|
)
|
|
{
|
|
HRESULT hr = WBEM_E_FAILED;
|
|
|
|
if ((NULL == pXML) || (NULL == pszObjectPath))
|
|
return WBEM_E_INVALID_PARAMETER;
|
|
|
|
// We need to make sure that only relative object paths are supplied in the second argument
|
|
CObjectPathParser pathParser (e_ParserAcceptRelativeNamespace);
|
|
ParsedObjectPath *pParsedPath;
|
|
pathParser.Parse (pszObjectPath, &pParsedPath) ;
|
|
if (pParsedPath)
|
|
{
|
|
if (pParsedPath->m_dwNumNamespaces != 0)
|
|
{
|
|
pathParser.Free(pParsedPath);
|
|
return WBEM_E_INVALID_PARAMETER;
|
|
}
|
|
pathParser.Free(pParsedPath);
|
|
}
|
|
|
|
|
|
// Connect to the requested namespace
|
|
IWbemServices *pService = NULL;
|
|
|
|
if (WBEM_S_NO_ERROR == (hr = m_connectionCache.GetConnectionByPath (pszNamespacePath, &pService)))
|
|
{
|
|
// 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
|
|
// TODO - Remove this double call to GetObject() if not required anymore
|
|
if(WBEM_E_INVALID_PARAMETER == (hr = pService->GetObject (pszObjectPath, WBEM_FLAG_USE_AMENDED_QUALIFIERS, NULL, &pObject, NULL)))
|
|
hr = pService->GetObject (pszObjectPath, 0, NULL, &pObject, NULL);
|
|
if (WBEM_S_NO_ERROR == hr)
|
|
{
|
|
// Create a stream
|
|
IStream *pStream = NULL;
|
|
|
|
if (SUCCEEDED(CreateStreamOnHGlobal(NULL, TRUE, &pStream)))
|
|
{
|
|
// Now do the translation
|
|
BSTR schemaURL = NULL;
|
|
EnterCriticalSection (&m_cs);
|
|
|
|
CWmiToXml w2xml (pszNamespacePath, pStream, pObject, m_bAllowWMIExtensions,
|
|
m_iQualifierFilter, m_bHostFilter, m_iDTDVersion,
|
|
m_bNamespaceInDeclGroup, m_iClassOriginFilter, m_iDeclGroupType);
|
|
|
|
if (m_schemaURL)
|
|
schemaURL = SysAllocString (m_schemaURL);
|
|
|
|
LeaveCriticalSection (&m_cs);
|
|
|
|
if (SUCCEEDED(hr = w2xml.MapObject (schemaURL)))
|
|
hr = SaveStreamAsBSTR (pStream, pXML);
|
|
|
|
SysFreeString (schemaURL);
|
|
pStream->Release ();
|
|
}
|
|
else
|
|
hr = WBEM_E_FAILED;
|
|
|
|
pObject->Release ();
|
|
}
|
|
pService->Release();
|
|
}
|
|
|
|
if (FAILED(hr))
|
|
m_hResult = hr;
|
|
|
|
return hr;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// SCODE CXMLTranslator::ExecQuery
|
|
//
|
|
// DESCRIPTION:
|
|
//
|
|
// Transforms the query result set nto its equivalent XML representation
|
|
//
|
|
// PARAMETERS:
|
|
//
|
|
// pszNamespacePath The namespace path in which the object resides.
|
|
// 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::ExecQuery (
|
|
BSTR pszNamespacePath,
|
|
BSTR pszQueryString,
|
|
BSTR *pXML
|
|
)
|
|
{
|
|
HRESULT hr = WBEM_E_FAILED;
|
|
|
|
if ((NULL == pXML) || (NULL == pszNamespacePath) || (NULL == pszQueryString))
|
|
return WBEM_E_INVALID_PARAMETER;
|
|
|
|
// Connect to the requested namespace
|
|
IWbemServices *pService = NULL;
|
|
|
|
if (WBEM_S_NO_ERROR == (hr = m_connectionCache.GetConnectionByPath (pszNamespacePath, &pService)))
|
|
{
|
|
// Perform the query
|
|
IEnumWbemClassObject *pEnum = NULL;
|
|
BSTR pszQueryLanguage = SysAllocString (L"WQL");
|
|
bool bMustFreeQueryString = false;
|
|
|
|
// If we are doing a select, make sure we add in __CLASS, __PATH, __GENUS and __SUPERCLASS
|
|
// as we need these for our own internal use
|
|
int i = 0;
|
|
int len = wcslen (pszQueryString);
|
|
|
|
while ((i < len) && iswspace (pszQueryString [i]))
|
|
i++;
|
|
|
|
if ((i < len) && (0 == _wcsnicmp (L"select", &pszQueryString [i], wcslen(L"select"))))
|
|
{
|
|
i += wcslen (L"select");
|
|
|
|
// Is the next non-space character a *
|
|
while ((i < len) && iswspace (pszQueryString [i]))
|
|
i++;
|
|
|
|
if ((i < len) && (L'*' != pszQueryString [i]))
|
|
{
|
|
// Need to add in the system properties
|
|
BSTR sysProps = SysAllocString (L" __CLASS, __PATH, __GENUS, __SUPERCLASS, ");
|
|
WCHAR *pNewQuery = new WCHAR [wcslen (pszQueryString) + wcslen (sysProps) + 1];
|
|
wcscpy (pNewQuery, L"select");
|
|
wcscat (pNewQuery, sysProps);
|
|
wcscat (pNewQuery, &pszQueryString [i]);
|
|
pszQueryString = SysAllocString (pNewQuery);
|
|
bMustFreeQueryString = true;
|
|
delete [] pNewQuery;
|
|
SysFreeString (sysProps);
|
|
}
|
|
}
|
|
|
|
|
|
// 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
|
|
// TODO - Remove this double call to GetObject() if not required anymore
|
|
if(WBEM_E_INVALID_PARAMETER == (hr = pService->ExecQuery (pszQueryLanguage, pszQueryString, WBEM_FLAG_USE_AMENDED_QUALIFIERS, NULL, &pEnum)))
|
|
hr = pService->ExecQuery (pszQueryLanguage, pszQueryString, 0, NULL, &pEnum);
|
|
if (WBEM_S_NO_ERROR == hr)
|
|
{
|
|
// Create a stream
|
|
IStream *pStream = NULL;
|
|
|
|
if (SUCCEEDED(CreateStreamOnHGlobal(NULL, TRUE, &pStream)))
|
|
{
|
|
// 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);
|
|
|
|
// Now do the translation
|
|
BSTR schemaURL = NULL;
|
|
EnterCriticalSection (&m_cs);
|
|
|
|
CWmiToXml w2xml (pszNamespacePath, pStream, pEnum, m_bAllowWMIExtensions,
|
|
m_iQualifierFilter, m_bHostFilter, m_iDTDVersion,
|
|
m_bNamespaceInDeclGroup, m_iClassOriginFilter, m_iDeclGroupType);
|
|
|
|
if (m_schemaURL)
|
|
schemaURL = SysAllocString (m_schemaURL);
|
|
|
|
LeaveCriticalSection (&m_cs);
|
|
|
|
if (SUCCEEDED (hr = w2xml.MapEnum (schemaURL)))
|
|
hr = SaveStreamAsBSTR (pStream, pXML);
|
|
|
|
SysFreeString (schemaURL);
|
|
pStream->Release ();
|
|
}
|
|
else
|
|
hr = WBEM_E_FAILED;
|
|
|
|
pEnum->Release ();
|
|
}
|
|
|
|
if (bMustFreeQueryString)
|
|
SysFreeString (pszQueryString);
|
|
|
|
SysFreeString (pszQueryLanguage);
|
|
pService->Release();
|
|
}
|
|
|
|
if (FAILED(hr))
|
|
m_hResult = hr;
|
|
|
|
return hr;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// HRESULT CXMLTranslator::SaveStreamAsBSTR
|
|
//
|
|
// DESCRIPTION:
|
|
//
|
|
// Returns the stream contents as a single BSTR
|
|
//
|
|
// PARAMETERS:
|
|
//
|
|
// pStream The stream from which the stream is to be extracted.
|
|
// pBstr Addresses the BSTR to hold the extracted string. If
|
|
// allocated by this function the caller must call
|
|
// SysFreeString to release the mempory.
|
|
//
|
|
// RETURN VALUES:
|
|
//
|
|
// WBEM_S_NO_ERROR success, pBstr contains the extracted text
|
|
// WBEM_E_FAILED otherwise
|
|
//
|
|
//***************************************************************************
|
|
|
|
HRESULT CXMLTranslator::SaveStreamAsBSTR (IStream *pStream, BSTR *pBstr)
|
|
{
|
|
HRESULT hr = WBEM_E_FAILED;
|
|
|
|
/*
|
|
FILE *outputFile = fopen( "//xml.htm", "w");
|
|
if(!outputFile)
|
|
return WBEM_E_FAILED;
|
|
*/
|
|
|
|
|
|
// Write the XML into the supplied BSTR
|
|
|
|
STATSTG statstg;
|
|
if (SUCCEEDED(pStream->Stat(&statstg, STATFLAG_NONAME)))
|
|
{
|
|
ULONG cbSize = (statstg.cbSize).LowPart;
|
|
OLECHAR *pText = new OLECHAR [(cbSize/2) + 1];
|
|
|
|
if (SUCCEEDED(pStream->Read(pText, cbSize, NULL)))
|
|
{
|
|
// Terminate the string
|
|
pText [cbSize/2] = NULL;
|
|
|
|
// The following must be freed by the caller using SysFreeString
|
|
*pBstr =SysAllocString (pText);
|
|
delete [] pText;
|
|
hr = WBEM_S_NO_ERROR;
|
|
}
|
|
}
|
|
|
|
// fclose(outputFile);
|
|
|
|
return hr;
|
|
}
|