// Copyright (c) 1997-2001 Microsoft Corporation, All Rights Reserved #include "precomp.h" #include #include "..\SingleView\icon.h" #include "..\SingleView\utils.h" #include #include #include #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; dwNamespacem_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; }