939 lines
26 KiB
C++
939 lines
26 KiB
C++
|
//=============================================================================
|
||
|
// This file contains the code for the classes which implement a live WMI
|
||
|
// data source.
|
||
|
//=============================================================================
|
||
|
|
||
|
#include "stdafx.h"
|
||
|
#include "wmilive.h"
|
||
|
#include "resource.h"
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// It's necessary to modify the security settings on a new WMI interface.
|
||
|
//-----------------------------------------------------------------------------
|
||
|
|
||
|
inline HRESULT ChangeWBEMSecurity(IUnknown * pUnknown)
|
||
|
{
|
||
|
IClientSecurity * pCliSec = NULL;
|
||
|
|
||
|
HRESULT hr = pUnknown->QueryInterface(IID_IClientSecurity, (void **) &pCliSec);
|
||
|
if (FAILED(hr))
|
||
|
return hr;
|
||
|
|
||
|
hr = pCliSec->SetBlanket(pUnknown, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL, RPC_C_AUTHN_LEVEL_PKT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE);
|
||
|
pCliSec->Release();
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
//=============================================================================
|
||
|
// CWMILiveObject Functions
|
||
|
//
|
||
|
// The constructor/destructor are really straight forward.
|
||
|
//=============================================================================
|
||
|
|
||
|
CWMILiveObject::CWMILiveObject() : m_pObject(NULL), m_pServices(NULL)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
CWMILiveObject::~CWMILiveObject()
|
||
|
{
|
||
|
if (m_pObject != NULL)
|
||
|
{
|
||
|
m_pObject->Release();
|
||
|
m_pObject = NULL;
|
||
|
}
|
||
|
|
||
|
if (m_pServices != NULL)
|
||
|
{
|
||
|
m_pServices->Release();
|
||
|
m_pServices = NULL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// The Create functions will either create the object from a WMI object, or
|
||
|
// from a service pointer and a path.
|
||
|
//-----------------------------------------------------------------------------
|
||
|
|
||
|
HRESULT CWMILiveObject::Create(IWbemServices * pServices, IWbemClassObject * pObject)
|
||
|
{
|
||
|
ASSERT(pObject && "calling CWMILiveObject::Create with a null object");
|
||
|
if (m_pObject != NULL)
|
||
|
m_pObject->Release();
|
||
|
|
||
|
m_pObject = pObject;
|
||
|
if (m_pObject)
|
||
|
m_pObject->AddRef();
|
||
|
|
||
|
m_pServices = pServices;
|
||
|
if (m_pServices)
|
||
|
m_pServices->AddRef();
|
||
|
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
HRESULT CWMILiveObject::Create(IWbemServices * pServices, LPCTSTR szObjectPath)
|
||
|
{
|
||
|
ASSERT(pServices && szObjectPath);
|
||
|
if (m_pObject != NULL)
|
||
|
{
|
||
|
m_pObject->Release();
|
||
|
m_pObject = NULL; // must be NULL or GetObject bitches
|
||
|
}
|
||
|
|
||
|
#ifdef UNICODE
|
||
|
BSTR bstrPath = SysAllocString(szObjectPath);
|
||
|
#else
|
||
|
USES_CONVERSION;
|
||
|
LPOLESTR szWidePath = T2OLE(szObjectPath);
|
||
|
BSTR bstrPath = SysAllocString(szWidePath);
|
||
|
#endif
|
||
|
|
||
|
HRESULT hr;
|
||
|
if (bstrPath)
|
||
|
{
|
||
|
hr = pServices->GetObject(bstrPath, 0L, NULL, &m_pObject, NULL);
|
||
|
SysFreeString(bstrPath);
|
||
|
}
|
||
|
else
|
||
|
hr = E_OUTOFMEMORY;
|
||
|
|
||
|
m_pServices = pServices;
|
||
|
if (m_pServices)
|
||
|
m_pServices->AddRef();
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// The simple GetValue returns the named value as a variant.
|
||
|
//
|
||
|
// The pointer to an existing uninitialized VARIANT structure that receives
|
||
|
// the property value, if found. Because this is an output parameter, this
|
||
|
// method calls VariantInit on this VARIANT, so you must be sure that this
|
||
|
// is not pointing to an active VARIANT.
|
||
|
//
|
||
|
// Note: You must call VariantClear on the returned VARIANT when its value
|
||
|
// is no longer required. This will prevent memory leaks in the client process.
|
||
|
//-----------------------------------------------------------------------------
|
||
|
|
||
|
HRESULT CWMILiveObject::GetValue(LPCTSTR szProperty, VARIANT * pvarValue)
|
||
|
{
|
||
|
ASSERT(szProperty && pvarValue);
|
||
|
if (m_pObject == NULL)
|
||
|
{
|
||
|
ASSERT(0 && "CWMILiveObject::GetValue called on a null object");
|
||
|
return E_FAIL;
|
||
|
}
|
||
|
|
||
|
#ifdef UNICODE
|
||
|
BSTR bstrProperty = SysAllocString(szProperty);
|
||
|
#else
|
||
|
USES_CONVERSION;
|
||
|
LPOLESTR szWideProperty = T2OLE(szProperty);
|
||
|
BSTR bstrProperty = SysAllocString(szWideProperty);
|
||
|
#endif
|
||
|
|
||
|
HRESULT hr;
|
||
|
if (bstrProperty)
|
||
|
{
|
||
|
hr = m_pObject->Get(bstrProperty, 0L, pvarValue, NULL, NULL);
|
||
|
SysFreeString(bstrProperty);
|
||
|
|
||
|
if (FAILED(hr))
|
||
|
hr = E_MSINFO_NOPROPERTY;
|
||
|
}
|
||
|
else
|
||
|
hr = E_FAIL;
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Get the named value as a string. Handle this even if the result is an
|
||
|
// array of values. The caller is responsible for freeing the string.
|
||
|
//-----------------------------------------------------------------------------
|
||
|
|
||
|
HRESULT CWMILiveObject::GetValueString(LPCTSTR szProperty, CString * pstrValue)
|
||
|
{
|
||
|
ASSERT(pstrValue);
|
||
|
VARIANT variant;
|
||
|
|
||
|
HRESULT hr = GetValue(szProperty, &variant);
|
||
|
if (SUCCEEDED(hr))
|
||
|
{
|
||
|
// If the property we just got is an array, we should convert it to string
|
||
|
// containing a list of the items in the array.
|
||
|
|
||
|
if ((variant.vt & VT_ARRAY) && (variant.vt & VT_BSTR) && variant.parray)
|
||
|
{
|
||
|
if (SafeArrayGetDim(variant.parray) == 1)
|
||
|
{
|
||
|
long lLower = 0, lUpper = 0;
|
||
|
|
||
|
SafeArrayGetLBound(variant.parray, 1, &lLower);
|
||
|
SafeArrayGetUBound(variant.parray, 1, &lUpper);
|
||
|
|
||
|
CComBSTR bstrWorking;
|
||
|
BSTR bstr = NULL;
|
||
|
for (long i = lLower; i <= lUpper; i++)
|
||
|
if (SUCCEEDED(SafeArrayGetElement(variant.parray, &i, (wchar_t*)&bstr)))
|
||
|
{
|
||
|
if (i != lLower)
|
||
|
bstrWorking.Append(L", ");
|
||
|
bstrWorking.AppendBSTR(bstr);
|
||
|
}
|
||
|
|
||
|
*pstrValue = bstrWorking;
|
||
|
}
|
||
|
}
|
||
|
else if (VariantChangeType(&variant, &variant, 0, VT_BSTR) == S_OK)
|
||
|
{
|
||
|
CComBSTR bstrWorking(V_BSTR(&variant));
|
||
|
|
||
|
unsigned int i, nLength = bstrWorking.Length();
|
||
|
BOOL fNonPrintingChar = FALSE;
|
||
|
|
||
|
for (i = 0; i < nLength && !fNonPrintingChar; i++)
|
||
|
if (((BSTR)bstrWorking)[i] < (WCHAR)0x20) // the 0x20 is from the XML spec
|
||
|
fNonPrintingChar = TRUE;
|
||
|
|
||
|
if (fNonPrintingChar)
|
||
|
{
|
||
|
CString strWorking;
|
||
|
for (i = 0; i < nLength; i++)
|
||
|
{
|
||
|
WCHAR c = ((BSTR)bstrWorking)[i];
|
||
|
if (c >= (WCHAR)0x20)
|
||
|
strWorking += c;
|
||
|
else
|
||
|
{
|
||
|
CString strTemp;
|
||
|
strTemp.Format(_T("&#x%04x;"), c);
|
||
|
strWorking += strTemp;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
*pstrValue = strWorking;
|
||
|
}
|
||
|
else
|
||
|
*pstrValue = bstrWorking;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
hr = E_MSINFO_NOVALUE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
VariantClear(&variant);
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Get the named value as a DWORD.
|
||
|
//-----------------------------------------------------------------------------
|
||
|
|
||
|
HRESULT CWMILiveObject::GetValueDWORD(LPCTSTR szProperty, DWORD * pdwValue)
|
||
|
{
|
||
|
ASSERT(pdwValue);
|
||
|
VARIANT variant;
|
||
|
|
||
|
HRESULT hr = GetValue(szProperty, &variant);
|
||
|
if (SUCCEEDED(hr))
|
||
|
{
|
||
|
if (VariantChangeType(&variant, &variant, 0, VT_I4) == S_OK)
|
||
|
*pdwValue = V_I4(&variant);
|
||
|
else
|
||
|
hr = E_MSINFO_NOVALUE;
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Get the named value as a SYSTEMTIME.
|
||
|
//-----------------------------------------------------------------------------
|
||
|
|
||
|
HRESULT CWMILiveObject::GetValueTime(LPCTSTR szProperty, SYSTEMTIME * psystimeValue)
|
||
|
{
|
||
|
ASSERT(psystimeValue);
|
||
|
VARIANT variant;
|
||
|
|
||
|
HRESULT hr = GetValue(szProperty, &variant);
|
||
|
if (SUCCEEDED(hr))
|
||
|
{
|
||
|
if (VariantChangeType(&variant, &variant, 0, VT_BSTR) == S_OK)
|
||
|
{
|
||
|
USES_CONVERSION;
|
||
|
LPTSTR szDate = OLE2T(V_BSTR(&variant));
|
||
|
|
||
|
// Parse the date string into the SYSTEMTIME struct. It would be better to
|
||
|
// get the date from WMI directly, but there was a problem with this. TBD -
|
||
|
// look into whether or not we can do this now.
|
||
|
|
||
|
ZeroMemory(psystimeValue, sizeof(SYSTEMTIME));
|
||
|
psystimeValue->wSecond = (unsigned short)_ttoi(szDate + 12); szDate[12] = _T('\0');
|
||
|
psystimeValue->wMinute = (unsigned short)_ttoi(szDate + 10); szDate[10] = _T('\0');
|
||
|
psystimeValue->wHour = (unsigned short)_ttoi(szDate + 8); szDate[ 8] = _T('\0');
|
||
|
psystimeValue->wDay = (unsigned short)_ttoi(szDate + 6); szDate[ 6] = _T('\0');
|
||
|
psystimeValue->wMonth = (unsigned short)_ttoi(szDate + 4); szDate[ 4] = _T('\0');
|
||
|
psystimeValue->wYear = (unsigned short)_ttoi(szDate + 0);
|
||
|
}
|
||
|
else
|
||
|
hr = E_MSINFO_NOVALUE;
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Get the named value as a double float.
|
||
|
//-----------------------------------------------------------------------------
|
||
|
|
||
|
HRESULT CWMILiveObject::GetValueDoubleFloat(LPCTSTR szProperty, double * pdblValue)
|
||
|
{
|
||
|
ASSERT(pdblValue);
|
||
|
VARIANT variant;
|
||
|
|
||
|
HRESULT hr = GetValue(szProperty, &variant);
|
||
|
if (SUCCEEDED(hr))
|
||
|
{
|
||
|
if (VariantChangeType(&variant, &variant, 0, VT_R8) == S_OK)
|
||
|
*pdblValue = V_R8(&variant);
|
||
|
else
|
||
|
hr = E_MSINFO_NOVALUE;
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Check for a value map value. If there isn't one, just use the untranslated
|
||
|
// value.
|
||
|
//-----------------------------------------------------------------------------
|
||
|
|
||
|
HRESULT CWMILiveObject::GetValueValueMap(LPCTSTR szProperty, CString * pstrValue)
|
||
|
{
|
||
|
CString strResult;
|
||
|
HRESULT hr = GetValueString(szProperty, &strResult);
|
||
|
|
||
|
if (SUCCEEDED(hr))
|
||
|
{
|
||
|
CString strClass;
|
||
|
CString strValueMapVal;
|
||
|
|
||
|
if (m_pServices && SUCCEEDED(GetValueString(_T("__CLASS"), &strClass)))
|
||
|
if (SUCCEEDED(CWMILiveHelper::CheckValueMap(m_pServices, strClass, szProperty, strResult, strValueMapVal)))
|
||
|
strResult = strValueMapVal;
|
||
|
}
|
||
|
|
||
|
*pstrValue = strResult;
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
//=============================================================================
|
||
|
// CWMILiveObjectCollection Functions
|
||
|
//
|
||
|
// The constructor and destructor for CWMILiveObjectCollection are very
|
||
|
// straightforward.
|
||
|
//=============================================================================
|
||
|
|
||
|
CWMILiveObjectCollection::CWMILiveObjectCollection(IWbemServices * pServices) : m_pServices(pServices), m_pEnum(NULL)
|
||
|
{
|
||
|
ASSERT(m_pServices);
|
||
|
if (m_pServices)
|
||
|
m_pServices->AddRef();
|
||
|
}
|
||
|
|
||
|
CWMILiveObjectCollection::~CWMILiveObjectCollection()
|
||
|
{
|
||
|
if (m_pServices)
|
||
|
m_pServices->Release();
|
||
|
|
||
|
if (m_pEnum)
|
||
|
m_pEnum->Release();
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Create the collection of WMI objects (a WMI enumerator) based on the
|
||
|
// class name and the requested properties.
|
||
|
//-----------------------------------------------------------------------------
|
||
|
|
||
|
HRESULT CWMILiveObjectCollection::Create(LPCTSTR szClass, LPCTSTR szProperties)
|
||
|
{
|
||
|
ASSERT(szClass);
|
||
|
|
||
|
if (m_pEnum)
|
||
|
m_pEnum->Release();
|
||
|
|
||
|
// Build the appopriate WQL query statement from the class and requested properties.
|
||
|
|
||
|
LPCTSTR szWQLProperties = (szProperties && szProperties[0]) ? szProperties : _T("*");
|
||
|
LPTSTR szQuery = new TCHAR[_tcsclen(szWQLProperties) + _tcsclen(szClass) + 14 /* length of "SELECT FROM " + 1 */];
|
||
|
if (szQuery == NULL)
|
||
|
return E_OUTOFMEMORY;
|
||
|
wsprintf(szQuery, _T("SELECT %s FROM %s"), szWQLProperties, szClass);
|
||
|
|
||
|
HRESULT hr = CreateWQL(szQuery);
|
||
|
delete [] szQuery;
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Create the collection of WMI objects (a WMI enumerator) based on the query.
|
||
|
//-----------------------------------------------------------------------------
|
||
|
|
||
|
HRESULT CWMILiveObjectCollection::CreateWQL(LPCTSTR szQuery)
|
||
|
{
|
||
|
ASSERT(szClass);
|
||
|
|
||
|
if (m_pEnum)
|
||
|
m_pEnum->Release();
|
||
|
|
||
|
// Perform the query using our saved services pointer.
|
||
|
|
||
|
HRESULT hr;
|
||
|
BSTR bstrLanguage = SysAllocString(L"WQL");
|
||
|
#ifdef UNICODE
|
||
|
BSTR bstrQuery = SysAllocString(szQuery);
|
||
|
#else
|
||
|
USES_CONVERSION;
|
||
|
LPOLESTR szWideQuery = T2OLE(szQuery);
|
||
|
BSTR bstrQuery = SysAllocString(szWideQuery);
|
||
|
#endif
|
||
|
|
||
|
if (bstrLanguage && bstrQuery)
|
||
|
hr = m_pServices->ExecQuery(bstrLanguage, bstrQuery, WBEM_FLAG_RETURN_IMMEDIATELY | WBEM_FLAG_FORWARD_ONLY, 0, &m_pEnum);
|
||
|
else
|
||
|
hr = E_OUTOFMEMORY;
|
||
|
|
||
|
if (SUCCEEDED(hr))
|
||
|
ChangeWBEMSecurity(m_pEnum);
|
||
|
|
||
|
if (bstrQuery)
|
||
|
SysFreeString(bstrQuery);
|
||
|
if (bstrLanguage)
|
||
|
SysFreeString(bstrLanguage);
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Create this class of an existing enumerator. This may be a little odd,
|
||
|
// since the enumerators will interact if both are advancing.
|
||
|
//-----------------------------------------------------------------------------
|
||
|
|
||
|
HRESULT CWMILiveObjectCollection::Create(IEnumWbemClassObject * pEnum)
|
||
|
{
|
||
|
if (m_pEnum)
|
||
|
m_pEnum->Release();
|
||
|
|
||
|
m_pEnum = pEnum;
|
||
|
|
||
|
if (m_pEnum)
|
||
|
{
|
||
|
m_pEnum->AddRef();
|
||
|
ChangeWBEMSecurity(m_pEnum);
|
||
|
}
|
||
|
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Return the next item in the WMI enumerator as a CWMILiveObject object.
|
||
|
//-----------------------------------------------------------------------------
|
||
|
|
||
|
HRESULT CWMILiveObjectCollection::GetNext(CWMIObject ** ppObject)
|
||
|
{
|
||
|
ASSERT(ppObject);
|
||
|
if (m_pEnum == NULL)
|
||
|
{
|
||
|
ASSERT(0 && "CWMILiveObjectCollection::GetNext called on a null enumerator");
|
||
|
return E_FAIL;
|
||
|
}
|
||
|
|
||
|
IWbemClassObject * pRealWMIObject = NULL;
|
||
|
ULONG uReturned;
|
||
|
|
||
|
HRESULT hr = m_pEnum->Next(TIMEOUT, 1, &pRealWMIObject, &uReturned);
|
||
|
if (hr == S_OK && uReturned == 1)
|
||
|
{
|
||
|
if (*ppObject == NULL)
|
||
|
*ppObject = new CWMILiveObject;
|
||
|
|
||
|
if (*ppObject)
|
||
|
{
|
||
|
hr = ((CWMILiveObject *)(*ppObject))->Create(m_pServices, pRealWMIObject); // this will AddRef the pointer
|
||
|
if (FAILED(hr))
|
||
|
{
|
||
|
delete (CWMILiveObject *)(*ppObject);
|
||
|
*ppObject = NULL;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
hr = E_OUTOFMEMORY;
|
||
|
pRealWMIObject->Release();
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
//=============================================================================
|
||
|
// CWMILiveHelper Functions
|
||
|
//
|
||
|
// The constructor/destructor are really straight forward.
|
||
|
//=============================================================================
|
||
|
|
||
|
CWMILiveHelper::CWMILiveHelper() : m_hrError(S_OK), m_strMachine(_T("")), m_strNamespace(_T("")), m_pServices(NULL)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
CWMILiveHelper::~CWMILiveHelper()
|
||
|
{
|
||
|
if (m_pServices)
|
||
|
{
|
||
|
m_pServices->Release();
|
||
|
m_pServices = NULL;
|
||
|
}
|
||
|
|
||
|
if (m_pIWbemServices)
|
||
|
{
|
||
|
m_pIWbemServices->Release();
|
||
|
m_pIWbemServices = NULL;
|
||
|
}
|
||
|
|
||
|
Version5ClearCache();
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Enumerate creates a CWMILiveObjectCollection based on the class.
|
||
|
//-----------------------------------------------------------------------------
|
||
|
|
||
|
HRESULT CWMILiveHelper::Enumerate(LPCTSTR szClass, CWMIObjectCollection ** ppCollection, LPCTSTR szProperties)
|
||
|
{
|
||
|
ASSERT(m_pServices);
|
||
|
if (m_pServices == NULL)
|
||
|
return E_FAIL;
|
||
|
|
||
|
ASSERT(ppCollection);
|
||
|
if (ppCollection == NULL)
|
||
|
return E_INVALIDARG;
|
||
|
|
||
|
CWMILiveObjectCollection * pLiveCollection;
|
||
|
|
||
|
if (*ppCollection)
|
||
|
pLiveCollection = (CWMILiveObjectCollection *) *ppCollection;
|
||
|
else
|
||
|
pLiveCollection = new CWMILiveObjectCollection(m_pServices);
|
||
|
|
||
|
if (pLiveCollection == NULL)
|
||
|
return E_FAIL; // TBD - memory failure
|
||
|
|
||
|
CString strProperties(szProperties);
|
||
|
StringReplace(strProperties, _T("MSIAdvanced"), _T(""));
|
||
|
|
||
|
HRESULT hr = pLiveCollection->Create(szClass, strProperties);
|
||
|
if (SUCCEEDED(hr))
|
||
|
*ppCollection = (CWMIObjectCollection *) pLiveCollection;
|
||
|
else
|
||
|
delete pLiveCollection;
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// WQLQuery creates a CWMILiveObjectCollection based on the query.
|
||
|
//-----------------------------------------------------------------------------
|
||
|
|
||
|
HRESULT CWMILiveHelper::WQLQuery(LPCTSTR szQuery, CWMIObjectCollection ** ppCollection)
|
||
|
{
|
||
|
ASSERT(m_pServices);
|
||
|
if (m_pServices == NULL)
|
||
|
return E_FAIL;
|
||
|
|
||
|
ASSERT(ppCollection);
|
||
|
if (ppCollection == NULL)
|
||
|
return E_INVALIDARG;
|
||
|
|
||
|
CWMILiveObjectCollection * pLiveCollection;
|
||
|
|
||
|
if (*ppCollection)
|
||
|
pLiveCollection = (CWMILiveObjectCollection *) *ppCollection;
|
||
|
else
|
||
|
pLiveCollection = new CWMILiveObjectCollection(m_pServices);
|
||
|
|
||
|
if (pLiveCollection == NULL)
|
||
|
return E_FAIL; // TBD - memory failure
|
||
|
|
||
|
HRESULT hr = pLiveCollection->CreateWQL(szQuery);
|
||
|
if (SUCCEEDED(hr))
|
||
|
*ppCollection = (CWMIObjectCollection *) pLiveCollection;
|
||
|
else
|
||
|
delete pLiveCollection;
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Get the named object.
|
||
|
//-----------------------------------------------------------------------------
|
||
|
|
||
|
HRESULT CWMILiveHelper::GetObject(LPCTSTR szObjectPath, CWMIObject ** ppObject)
|
||
|
{
|
||
|
ASSERT(ppObject);
|
||
|
if (ppObject == NULL)
|
||
|
return E_INVALIDARG;
|
||
|
|
||
|
CString strPath(szObjectPath);
|
||
|
|
||
|
if (strPath.Find(_T(":")) == -1)
|
||
|
{
|
||
|
// The path passed in is not a full object path if it doesn't have a colon.
|
||
|
|
||
|
CString strMachine(_T("."));
|
||
|
CString strNamespace(_T("cimv2"));
|
||
|
|
||
|
if (!m_strMachine.IsEmpty())
|
||
|
strMachine = m_strMachine;
|
||
|
|
||
|
if (!m_strNamespace.IsEmpty())
|
||
|
strNamespace = m_strNamespace;
|
||
|
|
||
|
strPath = CString(_T("\\\\")) + strMachine + CString(_T("\\root\\")) + strNamespace + CString(_T(":")) + strPath;
|
||
|
}
|
||
|
|
||
|
HRESULT hr = E_FAIL;
|
||
|
CWMILiveObject * pObject = NULL;
|
||
|
if (m_pServices)
|
||
|
{
|
||
|
pObject = new CWMILiveObject;
|
||
|
if (pObject)
|
||
|
hr = pObject->Create(m_pServices, strPath);
|
||
|
}
|
||
|
|
||
|
if (SUCCEEDED(hr))
|
||
|
*ppObject = pObject;
|
||
|
else if (pObject)
|
||
|
delete pObject;
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Create this WMI helper based on the machine and namespace.
|
||
|
//-----------------------------------------------------------------------------
|
||
|
|
||
|
HRESULT CWMILiveHelper::Create(LPCTSTR szMachine, LPCTSTR szNamespace)
|
||
|
{
|
||
|
if (m_pServices)
|
||
|
m_pServices->Release();
|
||
|
|
||
|
m_strMachine = _T(".");
|
||
|
if (szMachine && *szMachine)
|
||
|
{
|
||
|
m_strMachine = szMachine;
|
||
|
if (m_strMachine.Left(2) == _T("\\\\"))
|
||
|
m_strMachine = m_strMachine.Right(m_strMachine.GetLength() - 2);
|
||
|
}
|
||
|
|
||
|
m_strNamespace = _T("cimv2");
|
||
|
if (szNamespace && *szNamespace)
|
||
|
m_strNamespace = szNamespace;
|
||
|
|
||
|
// We get a WBEM interface pointer by first creating a WBEM locator interface, then
|
||
|
// using it to connect to a server to get an IWbemServices pointer.
|
||
|
|
||
|
CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_PKT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, 0);
|
||
|
IWbemServices * pService = NULL;
|
||
|
IWbemLocator * pIWbemLocator = NULL;
|
||
|
|
||
|
HRESULT hr = CoCreateInstance(CLSID_WbemLocator, NULL, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID *) &pIWbemLocator);
|
||
|
if (SUCCEEDED(hr))
|
||
|
{
|
||
|
if (pIWbemLocator)
|
||
|
{
|
||
|
CString strWMINamespace;
|
||
|
strWMINamespace.Format(_T("\\\\%s\\root\\%s"), m_strMachine, m_strNamespace);
|
||
|
BSTR pNamespace = strWMINamespace.AllocSysString();
|
||
|
if (pNamespace)
|
||
|
{
|
||
|
hr = pIWbemLocator->ConnectServer(pNamespace, NULL, NULL, 0L, 0L, NULL, NULL, &pService);
|
||
|
SysFreeString(pNamespace);
|
||
|
}
|
||
|
pIWbemLocator->Release();
|
||
|
pIWbemLocator = NULL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (pService && SUCCEEDED(hr))
|
||
|
ChangeWBEMSecurity(pService);
|
||
|
|
||
|
m_hrError = hr;
|
||
|
m_pServices = pService;
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Get a new WMI helper for the specified namespace.
|
||
|
//
|
||
|
// TBD - this should do something.
|
||
|
//-----------------------------------------------------------------------------
|
||
|
|
||
|
HRESULT CWMILiveHelper::NewNamespace(LPCTSTR szNamespace, CWMIHelper **ppNewHelper)
|
||
|
{
|
||
|
return E_FAIL;
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Get the current namespace of this WMI helper.
|
||
|
//
|
||
|
// TBD - this should do something.
|
||
|
//-----------------------------------------------------------------------------
|
||
|
|
||
|
HRESULT CWMILiveHelper::GetNamespace(CString * pstrNamespace)
|
||
|
{
|
||
|
return E_FAIL;
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Check to see if there is an associated value in a value map for this
|
||
|
// combination of class, property and value. This is lifted from the
|
||
|
// version 5.0 code.
|
||
|
//-----------------------------------------------------------------------------
|
||
|
|
||
|
CMapStringToString g_mapValueMapV7;
|
||
|
|
||
|
HRESULT CWMILiveHelper::CheckValueMap(IWbemServices * pServices, const CString& strClass, const CString& strProperty, const CString& strVal, CString &strResult)
|
||
|
{
|
||
|
IWbemClassObject * pWBEMClassObject = NULL;
|
||
|
HRESULT hrMap = S_OK, hr = S_OK;
|
||
|
VARIANT vArray, vMapArray;
|
||
|
IWbemQualifierSet * qual = NULL;
|
||
|
|
||
|
if (!pServices)
|
||
|
return E_FAIL;
|
||
|
|
||
|
// Check the cache of saved values.
|
||
|
|
||
|
CString strLookup = strClass + CString(_T(".")) + strProperty + CString(_T(":")) + strVal;
|
||
|
if (g_mapValueMapV7.Lookup(strLookup, strResult))
|
||
|
return S_OK;
|
||
|
|
||
|
// Get the class object (not instance) for this class.
|
||
|
|
||
|
CString strFullClass(_T("\\\\.\\root\\cimv2:"));
|
||
|
strFullClass += strClass;
|
||
|
BSTR bstrObjectPath = strFullClass.AllocSysString();
|
||
|
hr = pServices->GetObject(bstrObjectPath, WBEM_FLAG_USE_AMENDED_QUALIFIERS, NULL, &pWBEMClassObject, NULL);
|
||
|
::SysFreeString(bstrObjectPath);
|
||
|
|
||
|
if (FAILED(hr))
|
||
|
return hr;
|
||
|
|
||
|
// Get the qualifiers from the class object.
|
||
|
|
||
|
BSTR bstrProperty = strProperty.AllocSysString();
|
||
|
hr = pWBEMClassObject->GetPropertyQualifierSet(bstrProperty, &qual);
|
||
|
::SysFreeString(bstrProperty);
|
||
|
|
||
|
if (SUCCEEDED(hr) && qual)
|
||
|
{
|
||
|
// Get the ValueMap and Value arrays.
|
||
|
|
||
|
hrMap = qual->Get(L"ValueMap", 0, &vMapArray, NULL);
|
||
|
hr = qual->Get(L"Values", 0, &vArray, NULL);
|
||
|
|
||
|
if (SUCCEEDED(hr) && vArray.vt == (VT_BSTR | VT_ARRAY))
|
||
|
{
|
||
|
// Get the property value we're mapping.
|
||
|
|
||
|
long index;
|
||
|
if (SUCCEEDED(hrMap))
|
||
|
{
|
||
|
SAFEARRAY * pma = V_ARRAY(&vMapArray);
|
||
|
long lLowerBound = 0, lUpperBound = 0 ;
|
||
|
|
||
|
SafeArrayGetLBound(pma, 1, &lLowerBound);
|
||
|
SafeArrayGetUBound(pma, 1, &lUpperBound);
|
||
|
BSTR vMap;
|
||
|
|
||
|
for (long x = lLowerBound; x <= lUpperBound; x++)
|
||
|
{
|
||
|
SafeArrayGetElement(pma, &x, &vMap);
|
||
|
|
||
|
CString strMapVal(vMap);
|
||
|
if (0 == strVal.CompareNoCase(strMapVal))
|
||
|
{
|
||
|
index = x;
|
||
|
break; // found it
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Shouldn't hit this case - if mof is well formed
|
||
|
// means there is no value map where we are expecting one.
|
||
|
// If the strVal we are looking for is a number, treat it
|
||
|
// as an index for the Values array. If it's a string,
|
||
|
// then this is an error.
|
||
|
|
||
|
TCHAR * szTest = NULL;
|
||
|
index = _tcstol((LPCTSTR)strVal, &szTest, 10);
|
||
|
|
||
|
if (szTest == NULL || (index == 0 && *szTest != 0) || strVal.IsEmpty())
|
||
|
hr = E_FAIL;
|
||
|
}
|
||
|
|
||
|
// Lookup the string.
|
||
|
|
||
|
if (SUCCEEDED(hr))
|
||
|
{
|
||
|
SAFEARRAY * psa = V_ARRAY(&vArray);
|
||
|
long ix[1] = {index};
|
||
|
BSTR str2;
|
||
|
|
||
|
hr = SafeArrayGetElement(psa, ix, &str2);
|
||
|
if (SUCCEEDED(hr))
|
||
|
{
|
||
|
strResult = str2;
|
||
|
SysFreeString(str2);
|
||
|
hr = S_OK;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
hr = WBEM_E_VALUE_OUT_OF_RANGE;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
qual->Release();
|
||
|
}
|
||
|
|
||
|
if (SUCCEEDED(hr))
|
||
|
g_mapValueMapV7.SetAt(strLookup, strResult);
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// This function supplies a string for a given MSInfo specific HRESULT.
|
||
|
//-----------------------------------------------------------------------------
|
||
|
|
||
|
CString gstrNoValue, gstrNoProperty;
|
||
|
|
||
|
CString GetMSInfoHRESULTString(HRESULT hr)
|
||
|
{
|
||
|
switch (hr)
|
||
|
{
|
||
|
case E_MSINFO_NOVALUE:
|
||
|
if (gstrNoValue.IsEmpty())
|
||
|
{
|
||
|
::AfxSetResourceHandle(_Module.GetResourceInstance());
|
||
|
gstrNoValue.LoadString(IDS_ERROR_NOVALUE);
|
||
|
}
|
||
|
|
||
|
return (gstrNoValue);
|
||
|
|
||
|
case E_MSINFO_NOPROPERTY:
|
||
|
if (gstrNoProperty.IsEmpty())
|
||
|
{
|
||
|
::AfxSetResourceHandle(_Module.GetResourceInstance());
|
||
|
gstrNoProperty.LoadString(IDS_ERROR_NOPROPERTY);
|
||
|
}
|
||
|
|
||
|
return (gstrNoProperty);
|
||
|
|
||
|
default:
|
||
|
return (CString(_T("")));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// This is a wrapper for the GetObject() method in IWbemServices. This is
|
||
|
// called when there is a certain set of properties to get.
|
||
|
//
|
||
|
// Turns out this doesn't speed us up appreciably on our WMI uses.
|
||
|
//-----------------------------------------------------------------------------
|
||
|
|
||
|
/*
|
||
|
HRESULT CWMILiveObject::PartialInstanceGetObject(IWbemServices * pServices, BSTR bstrPath, IWbemClassObject ** ppObject, LPCTSTR szProperties)
|
||
|
{
|
||
|
HRESULT hr = WBEM_S_NO_ERROR;
|
||
|
|
||
|
if ((pServices != NULL) && (bstrPath != NULL) && (ppObject != NULL))
|
||
|
{
|
||
|
IWbemContext * pWbemContext = NULL;
|
||
|
hr = CoCreateInstance(CLSID_WbemContext, NULL, CLSCTX_INPROC_SERVER, IID_IWbemContext, (void**) &pWbemContext);
|
||
|
|
||
|
CStringArray csaProperties;
|
||
|
CString strProperties(szProperties), strProperty;
|
||
|
int index = 0;
|
||
|
while (!strProperties.IsEmpty())
|
||
|
{
|
||
|
strProperty = strProperties.SpanExcluding(_T(", "));
|
||
|
strProperties = strProperties.Mid(strProperty.GetLength());
|
||
|
strProperties.TrimLeft(_T(", "));
|
||
|
csaProperties.SetAtGrow(index++, strProperty);
|
||
|
}
|
||
|
|
||
|
if (pWbemContext != NULL)
|
||
|
{
|
||
|
variant_t vValue;
|
||
|
V_VT(&vValue) = VT_BOOL;
|
||
|
V_BOOL(&vValue) = VARIANT_TRUE;
|
||
|
|
||
|
// First set the value that says we are using Get extensions
|
||
|
if ((SUCCEEDED(hr = pWbemContext->SetValue(L"__GET_EXTENSIONS", 0L, &vValue))) &&
|
||
|
(SUCCEEDED(hr = pWbemContext->SetValue(L"__GET_EXT_CLIENT_REQUEST", 0L, &vValue))) )
|
||
|
{
|
||
|
// Delete any unneeded properties
|
||
|
pWbemContext->DeleteValue(L"__GET_EXT_KEYS_ONLY", 0L);
|
||
|
|
||
|
// Now build the array of properties
|
||
|
SAFEARRAYBOUND rgsabound [ 1 ] ;
|
||
|
|
||
|
rgsabound[0].cElements = csaProperties.GetSize() ;
|
||
|
rgsabound[0].lLbound = 0 ;
|
||
|
V_ARRAY(&vValue) = SafeArrayCreate ( VT_BSTR , 1 , rgsabound ) ;
|
||
|
if ( V_ARRAY(&vValue) )
|
||
|
{
|
||
|
V_VT(&vValue) = VT_BSTR | VT_ARRAY;
|
||
|
|
||
|
for (long x=0; x < csaProperties.GetSize(); x++)
|
||
|
{
|
||
|
bstr_t bstrProp = csaProperties[x];
|
||
|
|
||
|
SafeArrayPutElement(
|
||
|
V_ARRAY(&vValue),
|
||
|
&x,
|
||
|
(LPVOID) (BSTR) bstrProp);
|
||
|
}
|
||
|
|
||
|
// Put the array into the context object
|
||
|
if (SUCCEEDED(hr = pWbemContext->SetValue(L"__GET_EXT_PROPERTIES", 0L, &vValue)))
|
||
|
{
|
||
|
hr = pServices->GetObject(bstrPath, 0, pWbemContext, ppObject, 0);
|
||
|
|
||
|
vValue.Clear();
|
||
|
V_VT(&vValue) = VT_BOOL;
|
||
|
V_BOOL(&vValue) = VARIANT_FALSE;
|
||
|
pWbemContext->SetValue(L"__GET_EXTENSIONS", 0L, &vValue);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
hr = WBEM_E_INVALID_PARAMETER;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
hr = WBEM_E_INVALID_PARAMETER;
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
*/
|