windows-nt/Source/XPSP1/NT/admin/pchealth/sysinfo/control/wmihelp.cpp
2020-09-26 16:20:57 +08:00

441 lines
12 KiB
C++

//=============================================================================
// 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