2025-04-27 07:49:33 -04:00

2294 lines
54 KiB
C++

// Copyright (c) 1997-2001 Microsoft Corporation, All Rights Reserved
#include "precomp.h"
#include <wbemidl.h>
#include "..\SingleView\icon.h"
#include "..\SingleView\utils.h"
#include <genlex.h>
#include <opathlex.h>
#include <objpath.h>
#include "..\SingleView\hmomutil.h"
#include "..\SingleView\globals.h"
#include "..\SingleView\hmmverr.h"
#define FLAG_CLASS_IS_ASSOC 1
#define SZ_ARRAY_PREFIX "array of "
#define CCH_ARRAY_PREFIX 9
CObjectPathParser parser;
//*******************************************************************
// ConstructFullPath
//
// Given a path which may (or may not) be a relative path, convert the
// relative path to a full path using the given server and namespace
// values. If the path is initially an absolute path, just return the
// path as is without any modifications.
//
// Parameters:
// [in, out] COleVariant& varPath
// A path is passed in through this parameter. If it is a relative
// path, then the path is modified to be an absolute path
// using the given server name and namespace.
//
// [in] BSTR bstrServer
// The server name.
//
// [in] BSTR bstrNamespace
// The namespace.
//
// Returns:
// SCODE
// S_OK if a path is returned via varFullPath, a failure code
// otherwise.
//
//************************************************************************
SCODE MakePathAbsolute(COleVariant& varPath, BSTR bstrServer, BSTR bstrNamespace)
{
SCODE sc = S_OK;
if (bstrServer==NULL && bstrNamespace==NULL) {
// No server or namespace is given, so just use the exisiting path.
return S_OK;
}
BSTR bstrPath = varPath.bstrVal;
ASSERT(bstrPath != NULL);
ParsedObjectPath* pParsedPath = NULL;
int iStatus = parser.Parse(varPath.bstrVal, &pParsedPath);
if (iStatus != 0) {
if (pParsedPath) {
parser.Free(pParsedPath);
}
sc = E_FAIL;
return FALSE;
}
BOOL bIsAbsolutePath = FALSE;
if ((pParsedPath->m_pServer!=NULL) && (pParsedPath->m_dwNumNamespaces>0)) {
if (!IsEqual(pParsedPath->m_pServer, L".")) {
bIsAbsolutePath = TRUE;
}
}
if (bIsAbsolutePath) {
parser.Free(pParsedPath);
return S_OK;
}
// Use the server name from the path if one was given and it is not ".",
// otherwise use the server from the object containing the path.
CString sFullPath;
if ((pParsedPath->m_pServer!=NULL) && !IsEqual(pParsedPath->m_pServer, L".")) {
sFullPath = sFullPath + _T("\\\\") + pParsedPath->m_pServer;
}
else {
sFullPath = sFullPath + _T("\\\\") + bstrServer;
}
// Use the namespace contained in the path if one is given, othewise use the namespace
// of the object containing the path.
if (pParsedPath->m_dwNumNamespaces>0) {
CString sNamespace;
for (DWORD dwNamespace=0; dwNamespace<pParsedPath->m_dwNumNamespaces; ++ dwNamespace) {
sNamespace = sNamespace + pParsedPath->m_paNamespaces[dwNamespace];
if (dwNamespace != pParsedPath->m_dwNumNamespaces - 1) {
sNamespace += '\\';
}
}
sFullPath = sFullPath + _T("\\") + sNamespace;
}
else {
sFullPath = sFullPath + _T("\\") + bstrNamespace;
}
// Unparse the path to get the relative path and tack it onto the end.
LPWSTR pwszRelPath = NULL;
int nStatus2 = parser.Unparse(pParsedPath, &pwszRelPath);
ASSERT(nStatus2 == 0);
sFullPath = sFullPath + _T(":") + pwszRelPath;
varPath = sFullPath;
if (pwszRelPath) {
delete pwszRelPath;
}
parser.Free(pParsedPath);
return S_OK;
}
//***************************************************************************
// ServerAndNamespaceFromPath
//
// Extract the server name and namespace from a path if these path components
// present.
//
// Parameters:
// [out] COleVariant& varServer
// The server name value is returned here.
//
// [out] COleVaraint& varNamespace
// The namespace value is returned here.
//
// [in] BSTR bstrPath
// The path to parse.
//
// Returns:
// SCODE
// S_OK if the path was parsed successfully, a failure code otherwise.
//
//*****************************************************************************
SCODE ServerAndNamespaceFromPath(COleVariant& varServer, COleVariant& varNamespace, BSTR bstrPath)
{
SCODE sc = S_OK;
ParsedObjectPath* pParsedPath = NULL;
varServer.Clear();
varNamespace.Clear();
int iStatus = parser.Parse(bstrPath, &pParsedPath);
if (iStatus != 0) {
return E_FAIL;
}
if (pParsedPath->m_pServer) {
varServer = pParsedPath->m_pServer;
}
CString sNamespace;
if (pParsedPath->m_dwNumNamespaces > 0) {
for (DWORD dwNamespace=0; dwNamespace < pParsedPath->m_dwNumNamespaces; ++dwNamespace) {
sNamespace = sNamespace + pParsedPath->m_paNamespaces[dwNamespace];
if (dwNamespace < (pParsedPath->m_dwNumNamespaces - 1)) {
sNamespace += _T("\\");
}
}
varNamespace = sNamespace;
}
parser.Free(pParsedPath);
return S_OK;
}
//*****************************************************
// InSameNamespace
//
// Given a namespace and a path, check to see whether or
// not the path is within the same namespace. A relative
// path is assumed to reside in the same namespace.
//
// Parameters:
// [in] BSTR bstrNamespace
// The namespace.
//
// [in] BSTR bstrPath
// The path.
//
// Returns:
// TRUE if the path resides within the specified namespace,
// FALSE if it does not.
//
//******************************************************
BOOL InSameNamespace(BSTR bstrNamespace, BSTR bstrPath)
{
if (bstrNamespace==NULL && bstrPath==NULL) {
return TRUE;
}
if (bstrNamespace==NULL || bstrPath==NULL) {
return TRUE;
}
COleVariant varServerPath;
COleVariant varNamespacePath;
SCODE sc = ServerAndNamespaceFromPath(varServerPath, varNamespacePath, bstrPath);
if (FAILED(sc)) {
return FALSE;
}
CBSTR bsPath;
if (bstrNamespace[0] == '\\') {
CString s;
s = "\\\\";
s += varServerPath.bstrVal;
s += "\\";
s += varNamespacePath.bstrVal;
bsPath = s;
}
else {
bsPath = varNamespacePath.bstrVal;
}
bstrPath = (BSTR) bsPath;
BOOL bIsEqual = IsEqualNoCase(bstrNamespace, bstrPath);
return bIsEqual;
}
//******************************************************
// PathIsClass
//
// Examine a HMOM path to see if it is a class or an
// instance.
//
// Parameters:
// [in] LPCTSTR szPath
// The path to examine.
//
// Returns:
// BOOL
// TRUE if the path is a class, FALSE if it is an
// instance.
//
//**********************************************************
BOOL PathIsClass(LPCTSTR szPath)
{
while (*szPath) {
if (*szPath == '=') {
return FALSE;
}
++szPath;
}
return TRUE;
}
//******************************************************
// PathIsClass
//
// Examine a HMOM path to see if it is a class or an
// instance.
//
// Parameters:
// [out] SCODE& sc
// S_OK if the path was parsed and no errors were found.
// E_FAIL if there was a problem parsing the path.
//
// [in] BSTR bstrPath
// The path to examine.
//
// Returns:
// BOOL
// TRUE if the path is a class, FALSE if it is an
// instance. The return value is meaningful only if
// a success code is returned in sc.
//
//**********************************************************
BOOL PathIsClass(SCODE& sc, BSTR bstrPath)
{
sc = S_OK;
BSTR bstrT = bstrPath;
while (*bstrT) {
if (*bstrT == '=') {
return FALSE;
}
++bstrT;
}
ParsedObjectPath* pParsedPath = NULL;
int iStatus = parser.Parse(bstrPath, &pParsedPath);
if (iStatus != 0) {
sc = E_FAIL;
return FALSE;
}
BOOL bIsClass = pParsedPath->m_dwNumKeys == 0;
parser.Free(pParsedPath);
return bIsClass;
}
//*****************************************************
// InstPathToClassPath
//
// Given a path to an instance, return a path to the
// corresponding class.
//
// Parameters:
// [out] CString& sClassPath
//
// [in] LPCTSTR pszInstPath
//
// Returns:
// S_OK if successful, otherwise a failure code.
//
//*********************************************************
SCODE InstPathToClassPath(CString& sClassPath, LPCTSTR pszInstPath)
{
if (pszInstPath == NULL) {
return E_FAIL;
}
if (*pszInstPath == 0) {
// An empty path has no class and should take some lessons from
// Emily Post
return E_FAIL;
}
ParsedObjectPath* pParsedPath = NULL;
COleVariant varInstPath;
varInstPath = pszInstPath;
int nStatus1 = parser.Parse(varInstPath.bstrVal, &pParsedPath);
if (nStatus1 != 0) {
return E_FAIL;
}
if (pParsedPath->m_pClass == NULL) {
return E_FAIL;
}
CString sNamespace;
if (pParsedPath->m_dwNumNamespaces > 0) {
for (DWORD dwNamespace=0; dwNamespace < pParsedPath->m_dwNumNamespaces; ++dwNamespace) {
sNamespace = sNamespace + pParsedPath->m_paNamespaces[dwNamespace];
if (dwNamespace < (pParsedPath->m_dwNumNamespaces - 1)) {
sNamespace += _T("\\");
}
}
}
sClassPath.Empty();
if (pParsedPath->m_pServer) {
sClassPath = "\\\\";
sClassPath += pParsedPath->m_pServer;
sClassPath += "\\";
sClassPath += sNamespace;
sClassPath += ":";
}
sClassPath += pParsedPath->m_pClass;
parser.Free(pParsedPath);
return S_OK;
}
//SCODE LoadIconFromObject(IWbemClassObject* pInst, CSize size, CIcon& icon);
// SCODE GetIconPath(IWbemClassObject* pInst, CString& sIconPath);
SCODE GetClassName(IWbemClassObject* pInst, CString& sClassName);
// !!!CR: This duplicates the functionality in CHmmvCtl::ObjectIsClass
BOOL IsClass(IWbemClassObject* pInst)
{
VARIANT varGenus;
CBSTR bsPropname;
bsPropname = _T("__GENUS");
SCODE sc = pInst->Get((BSTR) bsPropname, 0, &varGenus, NULL, NULL);
ASSERT(SUCCEEDED(sc));
ASSERT(varGenus.vt == VT_I4);
if (varGenus.vt == VT_NULL) {
return FALSE;
}
else {
// varGenus.ChangeType(VT_I4);
return V_I4(&varGenus)== 1;
}
}
//****************************************************************
// ObjectIsDynamic
//
// This function tests an object to see whether or not it is dynamic.
// An object is dynamic if there is a class qualifier named "dynamic".
//
// Parameters:
// [out] SCODE& sc
// S_OK if the test was done successfully, a failure code
// otherwise.
//
// [in] IWbemClassObject* pco
// A pointer to the object to test.
//
// Returns:
// TRUE if the test was successful and the object is dynamic,
// FALSE otherwise.
//
//*****************************************************************
BOOL ObjectIsDynamic(SCODE& sc, IWbemClassObject* pco)
{
BOOL bIsDynamic = FALSE;
IWbemQualifierSet* pqs = NULL;
sc = pco->GetQualifierSet(&pqs); // Get instance attribute
if (SUCCEEDED(sc)) {
LONG lFlavor;
COleVariant varValue;
CBSTR bsQualName;
bsQualName = _T("dynamic");
sc = pqs->Get((BSTR) bsQualName, 0, &varValue, &lFlavor);
if (SUCCEEDED(sc)) {
ASSERT(varValue.vt == VT_BOOL);
if (varValue.vt == VT_BOOL) {
bIsDynamic = varValue.boolVal;
}
}
sc = S_OK;
pqs->Release();
}
return bIsDynamic;
}
SCODE GetCimtype(IWbemClassObject* pco, BSTR bstrPropname, CString& sCimtype)
{
BOOL bIsMethod = FALSE;
IWbemQualifierSet* pqs = NULL;
SCODE sc = pco->GetPropertyQualifierSet(bstrPropname, &pqs);
if (FAILED(sc)) {
return sc;
}
sc = GetCimtype(pqs, sCimtype);
pqs->Release();
return sc;
}
SCODE GetCimtype(IWbemQualifierSet* pqs, CString& sCimtype)
{
BOOL bIsMethod = FALSE;
COleVariant varValue;
LONG lFlavor = 0;
CBSTR bsQualName(_T("CIMTYPE"));
SCODE sc = pqs->Get((BSTR) bsQualName, 0, &varValue, &lFlavor);
if (FAILED(sc)) {
return sc;
}
if (varValue.vt != VT_BSTR) {
return E_FAIL;
}
sCimtype = varValue.bstrVal;
return S_OK;
}
//*********************************************************************
// PropertyIsReadOnly
//
// Test to see if the given property in an object is read-only.
//
// Parameters:
// IWbemClassObject* pco
// A pointer to the object containing the property.
//
// BSTR bstrPropName
// The name of the property to check.
//
// Returns:
// BOOL
// TRUE if the test was completed successfully and the property
// is read-only, FALSE otherwise.
//
//**********************************************************************
BOOL PropertyIsReadOnly(IWbemClassObject* pco, BSTR bstrPropName)
{
BOOL bIsReadOnly = FALSE;
IWbemQualifierSet* pqs = NULL;
SCODE sc;
sc = pco->GetPropertyQualifierSet(bstrPropName, &pqs);
if (SUCCEEDED(sc)) {
LONG lFlavor = 0;
COleVariant varValue;
CBSTR bsQualName;
bsQualName = _T("read");
sc = pqs->Get((BSTR) bsQualName, 0, &varValue, &lFlavor);
if (SUCCEEDED(sc)) {
ASSERT(varValue.vt == VT_BOOL);
if (varValue.vt == VT_BOOL) {
bIsReadOnly = varValue.boolVal;
if (bIsReadOnly) {
// We now know that the property was marked with a "read" capability.
// If it also has a "write" capability, then it is read/write.
varValue.Clear();
lFlavor = 0;
CBSTR bsQualName;
bsQualName = _T("write");
sc = pqs->Get((BSTR) bsQualName, 0, &varValue, &lFlavor);
if (SUCCEEDED(sc)) {
if (varValue.vt == VT_BOOL) {
if (varValue.boolVal) {
// The property is read/write and not just "read".
bIsReadOnly = FALSE;
}
}
}
} // bIsReadOnly
} // varValue.vt == VT_BOOL
} // SUCCEEDED(sc)
sc = S_OK;
pqs->Release();
}
return bIsReadOnly;
}
//*************************************************************
// IsSystemProperty
//
// Check to see if a property name is a system property.
// System properties begin with a double underscore "__".
//
// Parameters:
// [in] BSTR bstrPropName
// The property name to examine.
//
// Returns:
// BOOL
// TRUE if the property name is a system property name,
// FALSE otherwise.
//
//**************************************************************
BOOL IsSystemProperty(BSTR bstrPropName)
{
if (bstrPropName != NULL) {
if ((bstrPropName[0] == L'_') && (bstrPropName[1] == L'_')) {
return TRUE;
}
}
return FALSE;
}
//*****************************************************************
// GetClassName
//
// Get the class name of the current class or instance.
//
// Parameters:
// IWbemClassObject* pInst
// Pointer to the class name.
//
// CString& sClassName
// This is where the class name is returned.
//
// Returns:
// SCODE
// S_OK if a path was stored into sClassName.
//
//*****************************************************************
SCODE GetClassName(IWbemClassObject* pInst, CString& sClassName)
{
sClassName.Empty();
// Get the name of the instance's class.
COleVariant varClassName;
SCODE sc;
CBSTR bsPropname;
bsPropname = _T("__CLASS");
sc = pInst->Get((BSTR) bsPropname, 0, (VARIANT*) &varClassName, NULL, NULL);
if (sc == S_OK) {
VariantToCString(sClassName, varClassName);
}
else {
ASSERT(FALSE);
}
return sc;
}
//*************************************************************
// ObjectIsAssoc
//
// Check to see if an object is an association instance.
//
// Parameters:
// [in] IWbemClassObject* pco
// Pointer to the object to examine.
//
// [out] BOOL& bObjectIsAssoc
// TRUE if the object is an association instance,
// FALSE otherwise.
//
// Returns:
// SCODE
// S_OK if the test was successfully performed, FALSE otherwise.
//
//******************************************************************
SCODE ObjectIsAssocInstance(IWbemClassObject* pco, BOOL& bObjectIsAssoc)
{
SCODE sc;
CBSTR bsQualName;
bsQualName = _T("Association");
bObjectIsAssoc = GetBoolClassQualifier(sc, pco, (BSTR) bsQualName);
return sc;
}
//*****************************************************************
// GetBoolPropertyQualifier
//
// Get the value of a qualifier who's type must be VT_BOOL. If the
// value of the qualifier is NULL or a non-bool type, then an error
// code is returned.
//
// Parameters:
// [out] SCODE& sc
// The status code. S_OK if the value of the specified qualifier
// was successfully read and its type was VT_BOOL.
//
// [in] IWbemClassObject* pco
// Pointer to the HMOM object where the qualifier is stored.
//
// [in] BSTR bstrPropname
//
// [in] BSTR bstrQualifier
// The name of the qualifier.
//
// Returns:
// BOOL
// The value of the qualifier if it was read successfully, indeterminate
// if a failure code was returned via sc.
//
//*******************************************************************
BOOL GetBoolPropertyQualifier(SCODE& sc, IWbemClassObject* pco, BSTR bstrPropname, BSTR bstrQualifier)
{
BOOL bResult = FALSE;
IWbemQualifierSet* pqs = NULL;
sc = pco->GetPropertyQualifierSet(bstrPropname, &pqs);
// ASSERT(SUCCEEDED(sc));
if (SUCCEEDED(sc)) {
COleVariant varValue;
long lFlavor;
COleVariant varQualifierName;
varQualifierName = bstrQualifier;
sc = pqs->Get(varQualifierName.bstrVal, 0, &varValue, &lFlavor);
pqs->Release();
if (SUCCEEDED(sc)) {
if (varValue.vt == VT_BOOL) {
bResult = varValue.boolVal;
}
else {
sc = E_FAIL;
}
}
}
return bResult;
}
//----------------------------------------------------------------------
BOOL GetbstrPropertyQualifier(SCODE& sc,
IWbemClassObject *pco,
BSTR bstrPropname,
BSTR bstrQualifier,
BSTR bstrValue)
{
BOOL bResult = FALSE;
IWbemQualifierSet* pqs = NULL;
sc = pco->GetPropertyQualifierSet(bstrPropname, &pqs);
ASSERT(SUCCEEDED(sc));
if(SUCCEEDED(sc))
{
COleVariant varValue;
long lFlavor;
COleVariant varQualifierName;
varQualifierName = bstrQualifier;
sc = pqs->Get(varQualifierName.bstrVal, 0, &varValue, &lFlavor);
pqs->Release();
if(SUCCEEDED(sc))
{
if((varValue.vt == VT_BSTR) &&
(_wcsicmp(V_BSTR(&varValue), bstrValue) == 0))
{
bResult = TRUE;
}
else
{
sc = E_FAIL;
}
}
}
return bResult;
}
//*****************************************************************
// GetBoolClassQualifier
//
// Get the value of a qualifier who's type must be VT_BOOL. If the
// value of the qualifier is NULL or a non-bool type, then an error
// code is returned.
//
// Parameters:
// [out] SCODE& sc
// The status code. S_OK if the value of the specified qualifier
// was successfully read and its type was VT_BOOL.
//
// [in] IWbemClassObject* pco
// Pointer to the HMOM object where the qualifier is stored.
//
// [in] BSTR bstrQualifier
// The name of the qualifier.
//
// Returns:
// BOOL
// The value of the qualifier if it was read successfully, indeterminate
// if a failure code was returned via sc.
//
//*******************************************************************
BOOL GetBoolClassQualifier(SCODE& sc, IWbemClassObject* pco, BSTR bstrQualifier)
{
BOOL bResult = FALSE;
IWbemQualifierSet* pqs = NULL;
sc = pco->GetQualifierSet(&pqs);
ASSERT(SUCCEEDED(sc));
if (SUCCEEDED(sc)) {
COleVariant varValue;
long lFlavor;
COleVariant varQualifierName;
varQualifierName = bstrQualifier;
sc = pqs->Get(varQualifierName.bstrVal, 0, &varValue, &lFlavor);
pqs->Release();
if (SUCCEEDED(sc)) {
if (varValue.vt == VT_BOOL) {
bResult = varValue.boolVal;
}
else {
sc = E_FAIL;
}
}
}
return bResult;
}
//******************************************************************
// GetObjectLabel
//
// Get a label property for a class object. If the object doesn't
// have a label, then the objects __RELPATH is substituted.
//
// Parameters:
// IWbemClassObject* pObject
// Pointer to the object to get the label from.
//
// COleVariant& varLabelValue
// The label is returned here.
//
// BOOL bAssocTitleIsClass
// TRUE if the class name should be used for an association instance title.
//
// Returns:
// BOOL
// TRUE if the object was an association and the class name was
// used for lack of a better label.
//
//********************************************************************
void GetObjectLabel(IWbemClassObject* pObject, COleVariant& varLabelValue, BOOL bAssocTitleIsClass)
{
// Set the association node's label to the association instance label.
CMosNameArray aLabelPropNames;
CBSTR bsPropname;
bsPropname = _T("LABEL");
SCODE sc = aLabelPropNames.LoadPropNames(pObject, (BSTR) bsPropname, WBEM_FLAG_ONLY_IF_TRUE, NULL);
if (FAILED(sc)) {
ASSERT(FALSE);
}
if (aLabelPropNames.GetSize() == 0) {
if (bAssocTitleIsClass) {
BOOL bIsAssocInstance;
sc = ObjectIsAssocInstance(pObject, bIsAssocInstance);
if (bIsAssocInstance) {
CBSTR bsPropname;
bsPropname = _T("__CLASS");
sc = pObject->Get((BSTR) bsPropname, 0, &varLabelValue, NULL, NULL);
if (sc == S_OK) {
return;
}
}
}
bsPropname = _T("__RELPATH");
sc = pObject->Get((BSTR) bsPropname, 0, &varLabelValue, NULL, NULL);
if (FAILED(sc) || varLabelValue.vt!=VT_BSTR) {
varLabelValue = "";
}
}
else {
sc = pObject->Get(aLabelPropNames[0], 0, &varLabelValue, NULL, NULL);
ASSERT(SUCCEEDED(sc));
ASSERT(varLabelValue.vt == VT_BSTR);
if (IsEmptyString(varLabelValue.bstrVal)) {
// If the label in the database is bogus (ie empty), fall back to the
// relative path for the label.
bsPropname = _T("__RELPATH");
sc = pObject->Get((BSTR) bsPropname, 0, &varLabelValue, NULL, NULL);
ASSERT(SUCCEEDED(sc));
}
}
#ifdef _DEBUG
CString sLabelValue;
VariantToCString(sLabelValue, varLabelValue);
#endif //_DEBUG
ASSERT(varLabelValue.vt == VT_BSTR);
ASSERT(SUCCEEDED(sc));
return;
}
//******************************************************************
// GetLabelFromPath
//
// Map a path to an object label.
//
// Parameters:
// COleVariant& varLabelValue
// The label is returned here.
//
// BSTR bstrPath
// A path to the object. This is the path that is mapped to
// the label.
//
// Returns:
// SCODE
// S_OK if successful, otherwise a failure code.
//
//********************************************************************
SCODE GetLabelFromPath(COleVariant& varLabelValue, BSTR bstrPath)
{
ParsedObjectPath* pParsedPath = NULL;
int nStatus1 = parser.Parse(bstrPath, &pParsedPath);
if (nStatus1 == 0) {
LPWSTR pwszRelPath = NULL;
int nStatus2 = parser.Unparse(pParsedPath, &pwszRelPath);
if (nStatus2 == 0) {
varLabelValue = pwszRelPath;
delete pwszRelPath;
}
else {
// The parser could not generate a relative path from the
// parsed path.
// For lack of anything better, just use the original path.
ASSERT(FALSE);
varLabelValue = bstrPath;
}
parser.Free(pParsedPath);
}
else {
// The path could not be parsed. For lack of anything better, just
// use the original path.
varLabelValue = bstrPath;
}
return S_OK;
}
//***********************************************************
// CComparePaths::CompareNoCase
//
//
// Do a case insensitive comparison of two wide strings. This
// compare works even when one or both of the string pointers are
// NULL. A NULL pointer is taken to be less than any real string,
// even an empty one.
//
// Parameters:
// [in] LPWSTR pws1
// Pointer to the first string. This pointer can be NULL.
//
// [in] LPWSTR pws2
// Pointer to the second string. This pointer can be NULL.
//
// Returns:
// int
// Greater than zero if string1 is greater than string2.
// Zero if the two strings are equal.
// Less than zero if string 1 is less than string2.
//
//**************************************************************
int CComparePaths::CompareNoCase(LPWSTR pws1, LPWSTR pws2)
{
// Handle the case where one, or both of the string pointers are NULL
if (pws1 == NULL) {
if (pws2 == NULL) {
return 0; // Two null strings are equal
}
else {
return -1; // A null string is less than any real string.
}
}
if (pws2 == NULL) {
if (pws1 != NULL) {
return 1; // Any string is greater than a null string.
}
}
ASSERT(pws1 != NULL);
ASSERT(pws2 != NULL);
int iResult;
iResult = _wcsicmp( pws1, pws2);
return iResult;
}
//***************************************************************
// CComparePath::NormalizeKeyArray
//
// The key array is normalized by sorting the KeyRef's by key name.
// After two key arrays are sorted, they can be compared without
// by iterating through the list of keys and comparing corresponding
// array entries rather than trying searching the arrays for corresponding
// key names and then comparing the key values.
//
// Parameters:
// [in, out] ParsedObjectPath& path
// The parsed object path containing the key array to sort.
//
// Returns:
// Nothing. (The key array is sorted as a side effect).
//
//*****************************************************************
void CComparePaths::NormalizeKeyArray(ParsedObjectPath& path)
{
// Do a simple bubble sort where the "KeyRefs" with the smallest
// names are bubbled towards the top and the the KeyRefs with the
// largest names are bubbled toward the bottom.
for (DWORD dwKey1 = 0; dwKey1 < path.m_dwNumKeys; ++dwKey1) {
for (DWORD dwKey2 = dwKey1 + 1; dwKey2 < path.m_dwNumKeys; ++dwKey2) {
ASSERT(path.m_paKeys[dwKey1] != NULL);
KeyRef* pkr1 = path.m_paKeys[dwKey1];
ASSERT(pkr1 != NULL);
ASSERT(path.m_paKeys[dwKey2] != NULL);
KeyRef* pkr2 = path.m_paKeys[dwKey2];
ASSERT(pkr2 != NULL);
int iResult = CompareNoCase(pkr1->m_pName, pkr2->m_pName);
if (iResult > 0) {
// Swap the two keys;
path.m_paKeys[dwKey1] = pkr2;
path.m_paKeys[dwKey2] = pkr2;
}
}
}
}
//***********************************************************************
// CComparePaths::KeyValuesAreEqual
//
// Compare two key values to determine whether or not they are equal.
// To be equal, they must both be of the same type and their values
// must also be equal.
//
// Parameters:
// [in] VARAINT& variant1
// The first key value.
//
// [in] VARIANT& variant2
// The second key value.
//
// Returns:
// TRUE if the two values are the same, FALSE otherwise.
//
//**********************************************************************
BOOL CComparePaths::KeyValuesAreEqual(VARIANT& v1, VARIANT& v2)
{
ASSERT(v1.vt == v2.vt);
ASSERT(v1.vt==VT_BSTR || v1.vt == VT_I4);
ASSERT(v2.vt==VT_BSTR || v2.vt == VT_I4);
// Key values should always be VT_BSTR or VT_I4. We special case these
// two types to be efficient and punt on all the other types.
BOOL bIsEqual;
switch(v1.vt) {
case VT_BSTR:
if (v2.vt == VT_BSTR) {
bIsEqual = IsEqual(v1.bstrVal, v2.bstrVal);
return bIsEqual;
}
else {
return FALSE;
}
break;
case VT_I4:
if (v2.vt == VT_I4) {
bIsEqual = (v1.lVal == v2.lVal);
return bIsEqual;
}
else {
return FALSE;
}
break;
}
ASSERT(FALSE);
COleVariant var1;
COleVariant var2;
var1 = v1;
var2 = v2;
bIsEqual = (var1 == var2);
return bIsEqual;
}
//*******************************************************************
// CComparePaths::PathsRefSameObject
//
// Compare two parsed object paths to determine whether or not they
// they reference the same object. Note that the sever name and namespaces
// are not compared if they are missing from one of the paths.
//
// Parameters:
// [in] IWbemClassObject* pcoPath1
// A pointer to the object that corresponds to path1. If this
// pointer is NULL, then it will not be used in the path comparison.
// If a non-null value is given and the classes in the two paths
// are not the same, then this object pointer can be used to test
// to see if the object inherits from the class in path2. If so, then
// the classes are considered a match. This is useful if path2 points
// to the same object as path1, but path2 specifies the base class and
// path1 specifies the derived class.
//
// This is necessary for the association graph rendering code when
// the current object has
//
// [in] ParsedObjectPath* ppath1
// The first parsed path.
//
// [in] ParsedObjectPath* ppath2
// The second parsed path.
//
// Returns:
// BOOL
// TRUE if the two paths reference the same object, FALSE otherwise.
//
//*******************************************************************
BOOL CComparePaths::PathsRefSameObject(
/* in */ IWbemClassObject* pcoPath1,
/* in */ ParsedObjectPath* ppath1,
/* in */ ParsedObjectPath* ppath2)
{
if (ppath1 == ppath2) {
return TRUE;
}
if (ppath1==NULL || ppath2==NULL) {
return FALSE;
}
#if 0
// Check to see if a server name is specified for either path
// if so, the server name count is 1, otherwise zero.
UINT iNamespace1 = 0;
if (ppath1->m_pServer!=NULL) {
if (!IsEqual(ppath1->m_pServer, L".")) {
iNamespace1 = 1;
}
}
UINT iNamespace2 = 0;
if (ppath1->m_pServer!=NULL) {
if (!IsEqual(ppath2->m_pServer, L".")) {
iNamespace2 = 1;
}
}
// Relative paths don't specify a server, so we assume that the server
// for a relative path and any other path match and no further comparison is
// necessary.
if (iNamespace1!=0 && iNamespace2!=0) {
if (!IsEqual(ppath1->m_pServer, ppath2->m_pServer)) {
return FALSE;
}
}
// Relative paths don't specify name spaces, so we assume that the name spaces
// for a relative path and any other path match and no further comparison is
// necessary. Of course, this assumes that the namespace for a relative path
// is indeed the same as the other path.
if (ppath1->m_dwNumNamespaces!=0 && ppath2->m_dwNumNamespaces!=0) {
// Check to see if one of the namespaces are different.
if ((ppath1->m_dwNumNamespaces - iNamespace1) != (ppath2->m_dwNumNamespaces - iNamespace2)) {
return FALSE;
}
while((iNamespace1 < ppath1->m_dwNumNamespaces) && (iNamespace2 < ppath2->m_dwNumNamespaces)) {
if (!IsEqual(ppath1->m_paNamespaces[iNamespace1], ppath2->m_paNamespaces[iNamespace2])) {
return FALSE;
}
++iNamespace1;
++iNamespace2;
}
}
#endif //0
// Check to see if the classes are different.
if (!IsEqual(ppath1->m_pClass, ppath2->m_pClass)) {
if (pcoPath1) {
SCODE sc = pcoPath1->InheritsFrom(ppath2->m_pClass);
if (sc != WBEM_S_NO_ERROR) {
return FALSE;
}
}
else {
return FALSE;
}
}
// Check to see if any of the keys are different.
if (ppath1->m_dwNumKeys != ppath2->m_dwNumKeys) {
return FALSE;
}
KeyRef* pkr1;
KeyRef* pkr2;
// Handle single keys as a special case since "Class="KeyValue"" should
// be identical to "Class.keyName="KeyValue""
if ((ppath1->m_dwNumKeys==1) && (ppath2->m_dwNumKeys==1)) {
pkr1 = ppath1->m_paKeys[0];
pkr2 = ppath2->m_paKeys[0];
if (!IsEqual(pkr1->m_pName, pkr2->m_pName)) {
if (pkr1->m_pName!=NULL && pkr2->m_pName!=NULL) {
return FALSE;
}
}
if (KeyValuesAreEqual(pkr1->m_vValue, pkr2->m_vValue)) {
return TRUE;
}
else {
return FALSE;
}
}
NormalizeKeyArray(*ppath1);
NormalizeKeyArray(*ppath2);
for (DWORD dwKeyIndex = 0; dwKeyIndex < ppath1->m_dwNumKeys; ++dwKeyIndex) {
ASSERT(ppath1->m_paKeys[dwKeyIndex] != NULL);
ASSERT(ppath2->m_paKeys[dwKeyIndex] != NULL);
pkr1 = ppath1->m_paKeys[dwKeyIndex];
pkr2 = ppath2->m_paKeys[dwKeyIndex];
if (!IsEqual(pkr1->m_pName, pkr2->m_pName)) {
return FALSE;
}
if (!KeyValuesAreEqual(pkr1->m_vValue, pkr2->m_vValue)) {
return FALSE;
}
}
return TRUE;
}
//**************************************************************
// CComparePaths::PathsRefSameObject
//
// Check to see if two object paths point to the same object.
//
// Parameters:
// [in] IWbemClassObject* pcoPath1
// Pointer to the class object specified by bstrPath1 or NULL.
//
// BSTR bstrPath1
// The first object path.
//
// BSTR bstrPath2
// The second object path.
//
// Returns:
// BOOL
// TRUE if the two paths reference the same object in
// the database, FALSE otherwise.
//
//**************************************************************
BOOL CComparePaths::PathsRefSameObject(IWbemClassObject* pcoPath1, BSTR bstrPath1, BSTR bstrPath2)
{
ParsedObjectPath* pParsedPath1 = NULL;
ParsedObjectPath* pParsedPath2 = NULL;
int nStatus1;
int nStatus2;
nStatus1 = parser.Parse(bstrPath1, &pParsedPath1);
nStatus2 = parser.Parse(bstrPath2, &pParsedPath2);
BOOL bRefSameObject = FALSE;
if (nStatus1==0 && nStatus2==0) {
bRefSameObject = PathsRefSameObject(pcoPath1, pParsedPath1, pParsedPath2);
}
if (pParsedPath1) {
parser.Free(pParsedPath1);
}
if (pParsedPath2) {
parser.Free(pParsedPath2);
}
return bRefSameObject;
}
//**************************************************************
// ClassFromPath
//
// Extract the class name from an object path.
//
// Parameters:
// [out] COleVariant& varClass
// The class name is returned here.
//
// [in] BSTR bstrPath
// The path to extract the class name from.
//
// Returns:
// SCODE
// S_OK if a class was successfully extracted from
// the path, a E_FAIL if a class could not be extracted
// from the path.
//
//***************************************************************
SCODE ClassFromPath(COleVariant& varClass, BSTR bstrPath)
{
if (bstrPath == NULL) {
return E_FAIL;
}
if (*bstrPath == 0) {
return E_FAIL;
}
ParsedObjectPath* pParsedPath = NULL;
int nStatus1 = parser.Parse(bstrPath, &pParsedPath);
if (nStatus1 != 0) {
return E_FAIL;
}
SCODE sc = E_FAIL;
if (pParsedPath->m_pClass != NULL) {
varClass = pParsedPath->m_pClass;
sc = S_OK;
}
else {
varClass.Clear();
}
parser.Free(pParsedPath);
return sc;
}
//**************************************************************
// ClassIsAbstract
//
// Check to see if a class is abstract. By definition, a class
// is abstract if it has no "key" qualifiers on the class that
// are boolean and true.
//
// Parameters:
// [out] SCODE& sc
// S_OK if no HMOM errors occurred while searching for
// a "key" property set to true. The HMOM failure code
// if an error occurred.
//
// [in] IWbemClassObject* pco
// A pointer to the object to examine.
//
// Returns:
// BOOL
// TRUE if a key qualifier is found on the class such
// that its value is a bool and it is TRUE, FALSE otherwise.
//
//****************************************************************
BOOL ClassIsAbstract(SCODE& sc, IWbemClassObject* pco)
{
CBSTR bsQualName;
bsQualName = _T("abstract");
BOOL bClassIsAbstract = GetBoolClassQualifier(sc, pco, (BSTR) bsQualName);
if (SUCCEEDED(sc) && bClassIsAbstract) {
return TRUE;
}
CMosNameArray aKeys;
sc = aKeys.LoadPropNames(pco, NULL, WBEM_FLAG_KEYS_ONLY, NULL);
int nKeys = aKeys.GetSize();
if (nKeys == 0 && FAILED(sc)) {
// No keys were found.
return TRUE;
}
COleVariant varValue;
SCODE scTemp;
for (int iKey=0; iKey < nKeys; ++iKey) {
// Get the qualifier set for the property that has a "key" qualifier.
IWbemQualifierSet* pqs = NULL;
BSTR bstrPropName = aKeys[iKey];
scTemp = pco->GetPropertyQualifierSet(bstrPropName, &pqs);
if (FAILED(scTemp) || (pqs==NULL)) {
if (sc == S_OK) {
// Set the status to the first failure status if no "key" property
// is found that is a bool and is true.
sc = scTemp;
}
continue;
}
// Check to see if the "key" qualifier is a bool and that it is true.
LONG lFlavor = 0;
COleVariant varValue;
CBSTR bsQualName;
bsQualName = _T("key");
scTemp = pqs->Get((BSTR) bsQualName, 0, &varValue, &lFlavor);
pqs->Release();
if (FAILED(scTemp)) {
if (sc == S_OK) {
// Set the status to first failure status if no "key" property
// is found that is a bool and is true.
sc = scTemp;
}
continue;
}
if (varValue.vt != VT_BOOL) {
continue;
}
if (varValue.boolVal) {
sc = S_OK;
return FALSE;
}
}
// We didn't find any key property, so return false and any error status.
return TRUE;
}
//**************************************************************
// PropIsKey
//
// Check to see if the given property is a key.
//
// Parameters:
// [out] SCODE& sc
// S_OK if no HMOM errors occurred while searching for
// a "key" property set to true. The HMOM failure code
// if an error occurred.
//
// [in] IWbemClassObject* pco
// A pointer to the object to examine.
//
// [in] BSTR bstrPropname
// The property to check.
//
// Returns:
// BOOL
// TRUE if the property is a key, FALSE otherwise.
//
//****************************************************************
BOOL PropIsKey(SCODE& sc, IWbemClassObject* pco, BSTR bstrPropname)
{
// Get the qualifier set for the property that has a "key" qualifier.
IWbemQualifierSet* pqs = NULL;
sc = pco->GetPropertyQualifierSet(bstrPropname, &pqs);
if (FAILED(sc) || (pqs==NULL)) {
if (sc == S_OK) {
// Set the status to the first failure status if no "key" property
// is found that is a bool and is true.
sc = sc;
}
return FALSE;
}
// Check to see if the "key" qualifier is a bool and that it is true.
LONG lFlavor = 0;
COleVariant varValue;
CBSTR bsQualName;
bsQualName = _T("key");
sc = pqs->Get((BSTR) bsQualName, 0, &varValue, &lFlavor);
pqs->Release();
sc = S_OK;
if (FAILED(sc)) {
return FALSE;
}
if (varValue.vt != VT_BOOL) {
return FALSE;
}
if (varValue.boolVal) {
return TRUE;
}
return FALSE;
}
//*************************************************************
// MakeSafeArray
//
// Make a safe array of the specified size and element type.
//
// Parameters:
// SAFEARRAY FAR ** ppsaCreated
// A pointer to the place to return the safe array.
//
// VARTYPE vt
// The type of the elements.
//
// int nElements
// The number of elements.
//
// Returns:
// SCODE
// S_OK if successful, otherwise a failure code.
//
//*************************************************************
SCODE MakeSafeArray(SAFEARRAY FAR ** ppsaCreated, VARTYPE vt, int nElements)
{
SAFEARRAYBOUND rgsabound[1];
rgsabound[0].lLbound = 0;
rgsabound[0].cElements = nElements;
*ppsaCreated = SafeArrayCreate(vt,1, rgsabound);
return (*ppsaCreated == NULL) ? 0x80000001 : S_OK;
}
//*************************************************************
// PutStringInSafeArray
//
// Insert a string into a safe array.
//
// Parameters:
// SAFEARRAY FAR * psa
// Pointer to the safe array.
//
// CString& sValue
// The string value to insert into the array.
//
// int iIndex
// The index of the element to set. Indexes range from
// 0 ... n-1
//
// Returns:
// SCODE
// S_OK if successful.
//
//***************************************************************
SCODE PutStringInSafeArray(SAFEARRAY FAR * psa, CString& sValue, int iIndex)
{
#if 0
long ix[2];
ix[1] = 0;
ix[0] = iIndex;
#endif //0
long l = iIndex;
BSTR bstrValue = sValue.AllocSysString();
HRESULT hResult = SafeArrayPutElement(psa,&l,bstrValue);
SCODE sc = GetScode(hResult);
return sc;
}
//***********************************************************************
// CopyPathArrayByValue
//
// Copy the path array by value. This is necessary when saving context
// for the multiview control since the strings in the path array passed
// to ShowInstances may be deleted unexpectedly.
//
// Parameters:
// [out] COleVariant& covDst
// The place where the path array is copied to.
//
// [in] const VARIANTARG& varSrc
// The variant containing the path array.
//
// Returns:
// Nothing.
//
//***********************************************************************
void CopyPathArrayByValue(COleVariant& covDst, const VARIANTARG& varSrc)
{
covDst.Clear();
// First get the safe array pointer for the source.
SAFEARRAY* psaSrc = varSrc.parray;
if (varSrc.vt & VT_ARRAY && varSrc.vt & VT_BSTR) {
psaSrc = varSrc.parray;
}
else if (varSrc.vt & VT_VARIANT && varSrc.vt & VT_BYREF) {
if (varSrc.pvarVal->vt & VT_ARRAY && varSrc.pvarVal->vt & VT_BSTR) {
psaSrc = varSrc.pvarVal->parray;
}
else {
return;
}
}
else {
return;
}
LONG lLowerBound;
LONG lUpperBound;
HRESULT hr;
hr = SafeArrayGetLBound(psaSrc, 1, &lLowerBound);
hr = SafeArrayGetUBound(psaSrc, 1, &lUpperBound);
LONG nElements = (lUpperBound - lLowerBound) + 1;
SAFEARRAY *psaDst;
MakeSafeArray(&psaDst, VT_BSTR, nElements);
for (LONG lIndex = lLowerBound; lIndex <= lUpperBound; ++lIndex) {
BSTR bstrSrc;
BSTR bstrDst;
hr = SafeArrayGetElement(psaSrc, &lIndex, &bstrSrc);
bstrDst = ::SysAllocString(bstrSrc);
hr = SafeArrayPutElement(psaDst, &lIndex, bstrDst);
}
VARIANTARG var;
VariantInit(&var);
var.vt = VT_ARRAY | VT_BSTR;
var.parray = psaDst;
covDst.Clear();
covDst = var;
}
//******************************************************
// CMosNameArray::CMosNameArray
//
// Construct the CMosNameArray object.
//
// Parameters:
// None.
//
// Returns:
// Nothing.
//
//*****************************************************
CMosNameArray::CMosNameArray()
{
m_psa = NULL;
m_lLowerBound = 0;
m_lUpperBound = -1;
}
CMosNameArray::~CMosNameArray()
{
SafeArrayDestroy(m_psa);
}
void CMosNameArray::Clear()
{
if (m_psa) {
SafeArrayDestroy(m_psa);
m_psa = NULL;
m_lLowerBound = 0;
m_lUpperBound = -1;
}
}
//********************************************************
// CMosNameArray::operator[]
//
// Fetch the value of the string at the specified index
//
// Parameters:
// long lIndex
// The index of the attribute name. The index ranges
// from 0 to nElements - 1
//
// Returns:
// BSTR
// A BSTR pointer to the attribute name if it was successfully
// retrieved, otherwise NULL. The caller is responsible for
// performing a delete on the returned pointer when the caller
// is finished with the string.
//********************************************************
BSTR CMosNameArray::operator[](long lIndex)
{
// Rebase the index to start at m_LowerBound instead of 0
lIndex += m_lLowerBound;
ASSERT(lIndex>=m_lLowerBound && lIndex<=m_lUpperBound);
BSTR bstrValue;
long selector[2];
selector[0] = lIndex;
selector[1] = 0;
SCODE sc = SafeArrayGetElement(m_psa, selector, &bstrValue);
if (SUCCEEDED(sc)) {
return bstrValue;
}
else {
return NULL;
}
}
//***************************************************************
// CMosNameArray::LoadPropNames
//
// Load the property names from the IWbemClassObject into this
// CMosNameArray.
//
// Parameters:
// IWbemClassObject* pMosObj
// Pointer to the object to load the property names from.
//
// [in] long lFlags
// The flags parameter for IWbemClassObject::GetNames()
//
// Returns:
// SCODE
// S_OK if successful.
//
//**************************************************************
SCODE CMosNameArray::LoadPropNames(IWbemClassObject* pMosObj, long lFlags)
{
Clear();
SCODE sc = pMosObj->GetNames(NULL, lFlags, NULL, &m_psa);
if (SUCCEEDED(sc)) {
SafeArrayGetLBound(m_psa, 1, &m_lLowerBound);
SafeArrayGetUBound(m_psa, 1, &m_lUpperBound);
}
return sc;
}
//***************************************************************
// CMosNameArray::LoadPropNames
//
// Load the property names from the IWbemClassObject into this
// CMosNameArray.
//
// Parameters:
// IWbemClassObject* pMosObj
// Pointer to the object to load the property names from.
//
// BSTR bstrName
// The name of the attribute to query for. If NULL, all the
// properties are loaded.
//
// long lFlags
// Must be 0 if Name is NULL. Otherwise, must be one of:
// WBEM_FLAG_ONLY_IF_TRUE:
// Only properties with this attribute set are returned.
// pVal is ignored (should be NULL).
//
// HMM_ONLY_IF_FALSE:
// Only properties with this attribute NOT set are
// returned. pVal is ignored (should be NULL).
//
// HMM_ONLY_IF_IDENTICAL:
// pVal must point to an actual VARIANT. Only properties with
// this attribute set and equal to *pVal are returned.
//
//
// VARIANT* pVal
// Must be NULL if Name is NULL or if lFlags != HMM_ONLY_IF_IDENTICAL.
// Otherwise, indicates desired attribute value.
//
//
// Returns:
// SCODE
// S_OK if successful.
//
//**************************************************************
SCODE CMosNameArray::LoadPropNames(IWbemClassObject* pMosObj, BSTR bstrName, long lFlags, VARIANT* pVal)
{
Clear();
COleVariant varPropName;
varPropName = bstrName;
SCODE sc = pMosObj->GetNames(varPropName.bstrVal, lFlags, pVal, &m_psa);
if (SUCCEEDED(sc)) {
SafeArrayGetLBound(m_psa, 1, &m_lLowerBound);
SafeArrayGetUBound(m_psa, 1, &m_lUpperBound);
}
return sc;
}
//***************************************************************
// CMosNameArray::LoadAttribNames
//
// Load the attribute names from an IWbemQualifierSet into this
// CMosNameArray.
//
// Parameters:
// IWbemQualifierSet* pqs
// Pointer to the qualifier set to load the property names from.
//
// Returns:
// SCODE
// S_OK if successful.
//
//**************************************************************
SCODE CMosNameArray::LoadAttribNames(IWbemQualifierSet* pqs)
{
Clear();
SCODE sc = pqs->GetNames(WBEM_FLAG_ALWAYS, &m_psa);
if (SUCCEEDED(sc)) {
SafeArrayGetLBound(m_psa, 1, &m_lLowerBound);
SafeArrayGetUBound(m_psa, 1, &m_lUpperBound);
}
return sc;
}
//***************************************************************
// CMosNameArray::FindRefPropNames
//
// Find the names of all the reference properties of this object.
//
// Parameters:
// IWbemClassObject* pco
// Pointer to the HMOM class object.
//
// Returns:
// SCODE
// S_OK if successful, otherwise a failure code.
//
//***************************************************************
SCODE CMosNameArray::FindRefPropNames(IWbemClassObject* pco)
{
CMosNameArray aNames;
SCODE sc = LoadPropNames(pco, NULL, WBEM_FLAG_REFS_ONLY, NULL);
return sc;
}
//***************************************************************
// CMosNameArray::AddName
//
// Add a name to the end of the array.
//
// Parameters:
// [in] BSTR bstrName
// The value to add to the end of the array.
//
// Returns:
// SCODE
// S_OK if successful, otherwise a failure code.
//
//****************************************************************
SCODE CMosNameArray::AddName(BSTR bstrName)
{
// This method needs to be tested and debugged before
// it can be used.
ASSERT(FALSE);
return E_FAIL;
SCODE sc;
int nElementsInitial = GetSize();
HRESULT hResult;
SAFEARRAYBOUND sab;
sab.lLbound = m_lLowerBound;
sab.cElements = nElementsInitial + 1;
BOOL bDidCreateArray = FALSE;
if (m_psa == NULL) {
m_psa = SafeArrayCreate(VT_BSTR, 1, &sab);
if (m_psa == NULL) {
return E_FAIL;
}
m_lUpperBound = 0;
bDidCreateArray = TRUE;
}
else {
// Redimension the array to reseve space for the new element at
// the end of the array.
hResult = SafeArrayRedim(m_psa, &sab);
sc = GetScode(hResult);
ASSERT(SUCCEEDED(sc));
}
LONG lIndex = m_lUpperBound;
COleVariant varValue;
varValue = bstrName;
// Set the value of the new element.
long ix[2];
ix[1] = 0;
ix[0] = lIndex;
long l = lIndex ;
hResult = SafeArrayPutElement(m_psa,&l, bstrName);
sc = GetScode(hResult);
ASSERT(SUCCEEDED(sc));
if (FAILED(sc)) {
// Attempting to add the new element failed, restore things to their
// intial state.
if (bDidCreateArray) {
SafeArrayDestroy(m_psa);
m_psa = NULL;
}
else {
sab.lLbound = m_lLowerBound;
sab.cElements = nElementsInitial;
hResult = SafeArrayRedim(m_psa, &sab);
sc = GetScode(hResult);
ASSERT(SUCCEEDED(sc));
}
}
SafeArrayGetUBound(m_psa, 1, &m_lUpperBound);
BSTR bstrStoredName = (*this)[lIndex];
CString sName;
CString sStoredName;
sStoredName = bstrStoredName;
ASSERT(sStoredName == sName);
return sc;
}
//***************************************************************
// CMosNameArray::LoadPropAttribNames
//
// Load the attribute names from an IWbemClassObject into this
// CMosNameArray.
//
// Parameters:
// IWbemClassObject* pMosObj
// Pointer to the object to load the property names from.
//
// Returns:
// SCODE
// S_OK if successful.
//
//**************************************************************
SCODE CMosNameArray::LoadPropAttribNames(IWbemClassObject* pMosObj, BSTR bstrPropName)
{
Clear();
SCODE sc;
COleVariant varPropName;
IWbemQualifierSet* pAttribSet = NULL;
sc = pMosObj->GetPropertyQualifierSet(ToBSTR(varPropName), &pAttribSet);
if (SUCCEEDED(sc)) {
sc = LoadAttribNames(pAttribSet);
pAttribSet->Release();
}
if (SUCCEEDED(sc)) {
SafeArrayGetLBound(m_psa, 1, &m_lLowerBound);
SafeArrayGetUBound(m_psa, 1, &m_lUpperBound);
}
return sc;
}
//***************************************************************
// FindLabelProperty
//
// Given an IWbemClassObject, find the first property that has the
// "Label" attribute.
//
// Parameters:
// IWbemClassObject* pMosObj
// Pointer to the object to search.
//
// COleVariant& varLabel
// The value of the label property is returned here.
//
// BOOL& bDidFindLabel
// A reference used to return a flag indicating whether
// or not a label was found. Set to TRUE if a label property
// was found, found. Otherwise it is set to FALSE.
//
// Returns:
// SCODE
// S_OK if no error occurred.
//
//**************************************************************
SCODE FindLabelProperty(IWbemClassObject* pMosObj, COleVariant& varLabel, BOOL& bDidFindLabel)
{
bDidFindLabel = FALSE;
CMosNameArray aLabels;
CBSTR bsPropname;
bsPropname = _T("LABEL");
SCODE sc = aLabels.LoadPropNames(pMosObj, (BSTR)bsPropname, WBEM_FLAG_ONLY_IF_TRUE, NULL);
if (FAILED(sc)) {
// If there is no label, default it to the __RELPATH property
bsPropname = _T("__RELPATH");
sc = pMosObj->Get((BSTR)bsPropname, 0, &varLabel, NULL, NULL);
if (SUCCEEDED(sc)) {
bDidFindLabel = TRUE;
}
return sc;
}
if (aLabels.GetSize() < 1) {
// Object doesn't have a label property.
return sc;
}
sc = pMosObj->Get(aLabels[0], 0, &varLabel, NULL, NULL);
if (SUCCEEDED(sc)) {
bDidFindLabel = TRUE;
}
return sc;
}
typedef struct {
UINT ids;
LONG lValue;
}TMapStringToLong;
class CMapStringToLong
{
public:
void Load(TMapStringToLong* pMap, int nEntries);
BOOL Lookup(LPCTSTR key, LONG& lValue ) const;
private:
CMapStringToPtr m_map;
};
//*************************************************************
// CMapStringToLong::Load
//
// Given an array of TMapStringToLong entries, load the contents
// of this map so that the strings in the input array can be
// mapped to the corresponding values.
//
// Parameters:
// TMapStringToLong* pMap
// Pointer to an array of entries containing the resource ID of
// a string and the corresponding value to map the string to.
//
// int nEntries
// The number of entries in the array.
//
// Returns:
// Nothing.
//
//**************************************************************
void CMapStringToLong::Load(TMapStringToLong* pMap, int nEntries)
{
if (m_map.GetCount() > 0) {
return;
}
CString sKey;
while (--nEntries >= 0) {
sKey.LoadString(pMap->ids);
m_map.SetAt(sKey, (void*) pMap->lValue);
++pMap;
}
}
//**************************************************************
// CMapStringToLong::Lookup
//
// Lookup the given key string and return the corresponding value.
//
// Parameters:
// LPCTSTR key
// The key value string to lookup
//
// LONG& lValue
// The place to return the value corresponding to the
// key if the key was found.
//
// Returns:
// TRUE = The key was found and a value was returned via lValue.
// FALSE = The key was not found and no value was returned.
//
//**************************************************************
BOOL CMapStringToLong::Lookup( LPCTSTR key, LONG& lValue ) const
{
void* pVoid;
BOOL bFoundKey = m_map.Lookup(key, pVoid);
if (bFoundKey) {
lValue = (DWORD)(DWORD_PTR)pVoid; // NOTE: The pointer we stored REALY was a long
}
return bFoundKey;
}
CMapStringToLong mapCimType;
//*************************************************************
// MapCimtypeToString
//
// Map a CIMTYPE value to its closest string equivallent. This
// function is called for properties, such as system properties, that
// do not have a cimtype qualifier and yet we still need to display
// a string value in the "type" cells.
//
// Parameters:
// [out] CString& sCimtype
// The string value of cimtype is returned here.
//
// [in] CIMTYPE cimtype
// The cimom CIMTYPE value.
//
// Returns:
// SCODE
// S_OK if a known cimtype is specified, E_FAIL if
// an unexpected cimtype is encountered.
//
//*************************************************************
//********************************************************
// CimtypeFromVt
//
// Map a variant type to a cimtype. This method is useful
// because all cells in the grid must be assigned a CIMTYPE.
//
//
// Parameters:
// [in] VARTYPE vt
// The variant type.
//
// Returns:
// CIMTYPE
// The most appropriate CIMTYPE for representing the
// given VARTYPE.
//
//********************************************************
CIMTYPE CimtypeFromVt(VARTYPE vt)
{
CIMTYPE cimtype = CIM_EMPTY;
BOOL bIsArray = vt & VT_ARRAY;
vt = vt & VT_TYPEMASK;
switch(vt) {
case VT_UI1:
cimtype = CIM_UINT8;
break;
case VT_UI2:
cimtype = CIM_UINT16;
break;
case VT_UI4:
cimtype = CIM_UINT32;
break;
case VT_I1:
cimtype = CIM_SINT8;
break;
case VT_I2:
cimtype = CIM_SINT16;
break;
case VT_I4:
cimtype = CIM_SINT32;
break;
case VT_R4:
cimtype = CIM_REAL32;
break;
case VT_R8:
cimtype = CIM_REAL64;
break;
case VT_BOOL:
cimtype = CIM_BOOLEAN;
break;
case VT_BSTR:
default:
cimtype = CIM_STRING;
break;
}
if (bIsArray) {
cimtype |= CIM_FLAG_ARRAY;
}
return cimtype;
}