|
|
//=============================================================================
// Code used to manage threaded WMI refreshes.
//=============================================================================
#include "stdafx.h"
#if FALSE
//-----------------------------------------------------------------------------
// The CWMIObject abstract base class encapsulates a WMI object, which may
// in reality be a live WMI object, or an object recreated from the XML
// storage of an object.
//-----------------------------------------------------------------------------
class CWMIObject { public: CWMIObject(); virtual ~CWMIObject();
// The following methods return information about a property of this object.
//
// S_OK implies success
// E_MSINFO_NOPROPERTY means the named property doesn't exist
// E_MSINFO_NOVALUE means the property exists, but is empty
virtual HRESULT GetValue(LPCTSTR szProperty, VARIANT * pvarValue); virtual HRESULT GetValueString(LPCTSTR szProperty, LPTSTR * pszValue); virtual HRESULT GetValueDWORD(LPCTSTR szProperty, DWORD * pdwValue); virtual HRESULT GetValueTime(LPCTSTR szProperty, SYSTEMTIME * psystimeValue); virtual HRESULT GetValueDoubleFloat(LPCTSTR szProperty, double * pdblValue); virtual HRESULT GetValueValueMap(LPCTSTR szProperty, LPTSTR * pszValue); };
//-----------------------------------------------------------------------------
// The CWMIObjectCollection abstract base class encapsulates a collection
// of CWMIObject's. This collection may be treated like an enumeration.
// Subclases of this class may implement the collection as a WMI enumerator,
// or an existing blob of XML data.
//-----------------------------------------------------------------------------
class CWMIObjectCollection { public: CWMIObjectCollection(); virtual ~CWMIObjectCollection();
// The Create function creates the collection of objects (note - Create
// may be called multiple times on the same object). If the szProperties
// parameter is non-NULL, then it contains a comma delimited list of the
// minimum set of properties which should be included in the collection
// of objects. If it's NULL, then all available properties should be
// included.
virtual HRESULT Create(LPCTSTR szClass, LPCTSTR szProperties = NULL);
// The following two functions are used to manage the enumeration. GetNext
// returns the next enumerated CWMIObject. When there are no more objects,
// GetNext returns S_FALSE. Obviously, the caller is responsible for
// deleting the object returned.
virtual HRESULT GetNext(CWMIObject ** ppObject); };
//-----------------------------------------------------------------------------
// The CWMILiveObject implements a CWMIObject using a real WMI object. It
// can be created with either a IWbemClassObject pointer, or a services
// pointer and a path.
//-----------------------------------------------------------------------------
class CWMILiveObject : public CWMIObject { public: CWMILiveObject(); virtual ~CWMILiveObject();
// Functions inherited from the base class:
HRESULT GetValue(LPCTSTR szProperty, VARIANT * pvarValue); HRESULT GetValueString(LPCTSTR szProperty, LPTSTR * pszValue); HRESULT GetValueDWORD(LPCTSTR szProperty, DWORD * pdwValue); HRESULT GetValueTime(LPCTSTR szProperty, SYSTEMTIME * psystimeValue); HRESULT GetValueDoubleFloat(LPCTSTR szProperty, double * pdblValue); HRESULT GetValueValueMap(LPCTSTR szProperty, LPTSTR * pszValue);
// Functions specific to this subclass:
//
// Note - Create with an object pointer will addref() the pointer:
HRESULT Create(IWbemClassObject * pObject); HRESULT Create(IWbemServices * pServices, LPCTSTR szObjectPath);
private: IWbemClassObject * m_pObject; };
//-----------------------------------------------------------------------------
// The CWMILiveObjectCollection implements a collection of live WMI objects
// using a WMI enumerator. This collection can be created from an existing
// IEnumWbemClassObject pointer, from a WQL statement or from a WMI class name.
//-----------------------------------------------------------------------------
class CWMILiveObjectCollection { public: CWMILiveObjectCollection(IWbemServices * pServices); virtual ~CWMILiveObjectCollection();
// Functions inherited from the base class:
HRESULT Create(LPCTSTR szClass, LPCTSTR szProperties = NULL); HRESULT GetNext(CWMIObject ** ppObject);
// Functions specific to this subclass:
//
// Note - Create with an enum pointer will addref() the pointer:
public: HRESULT Create(IEnumWbemClassObject * pEnum);
private: IEnumWbemClassObject * m_pEnum; IWbemServices * m_pServices; };
//-----------------------------------------------------------------------------
// 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 : _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"), szClass, szWQLProperties);
// 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 = pService->ExecQuery(bstrLanguage, bstrQuery, WBEM_FLAG_RETURN_IMMEDIATELY, 0, &m_pEnum); else hr = E_OUTOFMEMORY; if (bstrQuery) SysFreeString(bstrQuery); if (bstrLanguage) SysFreeString(bstrLanguage);
delete [] szQuery; 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(); }
//-----------------------------------------------------------------------------
// 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) { *ppObject = new CWMILiveObject; if (*ppObject) hr = (*ppObject)->Create(pRealWMIObject); else hr = E_FAIL; // TBD memory error
}
return hr; }
//-----------------------------------------------------------------------------
// The constructor/destructor are really straight forward.
//-----------------------------------------------------------------------------
CWMILiveObject::CWMILiveObject() : m_pObject(NULL) { }
CWMILiveObject::~CWMILiveObject() { if (m_pObject != NULL) { m_pObject->Release(); m_pObject = NULL; } }
//-----------------------------------------------------------------------------
// The Create functions will either create the object from a WMI object, or
// from a service pointer and a path.
//-----------------------------------------------------------------------------
HRESULT CWMILiveObject::Create(IWbemClassObject * pObject) { ASSERT(pObject && "calling CWMILiveObject::Create with a null object"); if (m_pObject != NULL) { ASSERT(0 && "calling create on an already created CWMILiveObject"); m_pObject->Release(); }
m_pObject = pObject; if (m_pObject) m_pObject->AddRef();
return S_OK; }
HRESULT CWMILiveObject::Create(IWbemServices * pServices, LPCTSTR szObjectPath) { ASSERT(pServices && szObjectPath); if (m_pObject != NULL) { ASSERT(0 && "calling create on an already created CWMILiveObject"); 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_FAIL;
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 = 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.
//-----------------------------------------------------------------------------
HRESULT CWMILiveObject::GetValueString(LPCTSTR szProperty, LPTSTR * pszValue) { 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, 0, &lLower); SafeArrayGetUBound(variant.parray, 0, &lUpper);
CString strWorking; BSTR bstr = NULL; for (long i = lLower; i <= lUpper; i++) if (SUCCEEDED(SafeArrayGetElement(variant.parray, &i, (wchar_t*)&bstr))) { if (i != lLower) strWorking += _T(", "); strWorking += bstr; } *pstrValue = strWorking; } } else if (VariantChangeType(&variant, &variant, 0, VT_BSTR) == S_OK) { *pstrValue = V_BSTR(&variant); } else { hr = E_MSINFO_NOVALUE; } }
return hr; }
HRESULT CWMILiveObject::GetValueDWORD(LPCTSTR szProperty, DWORD * pdwValue) { return E_FAIL; }
HRESULT CWMILiveObject::GetValueTime(LPCTSTR szProperty, SYSTEMTIME * psystimeValue) { return E_FAIL; }
HRESULT CWMILiveObject::GetValueDoubleFloat(LPCTSTR szProperty, double * pdblValue) { return E_FAIL; }
HRESULT CWMILiveObject::GetValueValueMap(LPCTSTR szProperty, LPTSTR * pszValue) { return E_FAIL; } #endif
|