Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

420 lines
18 KiB

  1. //=============================================================================
  2. // File: gathint.h
  3. // Author: a-jammar
  4. // Covers: GATH_VALUE, GATH_FIELD, GATH_LINESPEC, GATH_LINE,
  5. // INTERNAL_CATEGORY, CDataProvider, CTemplateFileFunctions,
  6. // CRefreshFunctions
  7. //
  8. // Copyright (c) 1998-1999 Microsoft Corporation
  9. //
  10. // This header file is used for internal structures and constants which
  11. // don't need to be exposed to the rest of the world in gather.h.
  12. //
  13. // CDataProvider encapsulates WBEM functionality. This object is created
  14. // and maintained by the CDataGatherer object.
  15. //
  16. // CTemplateFileFunctions and CRefreshFunctions consist of static member
  17. // functions which implement template file reading and information refreshing
  18. // functionality. These are split out of the other classes to hide the
  19. // unnecessary clutter from gather.h. They are in classes simply to make
  20. // it easier for them to be "friend's" of CDataGatherer.
  21. //
  22. // OVERVIEW OF INTERNAL DATA STRUCTURES
  23. //
  24. // The INTERNAL_CATEGORY structure represents a category, and is stored by
  25. // the CDataGatherer object in a map between IDs and internal categories. It
  26. // contains general category information (name, relatives) plus the column and
  27. // line specifiers and data. The specifiers indicate where data should be
  28. // gotten, and how it should be presented. When a refresh is done, the actual
  29. // data is produced and saved.
  30. //
  31. // A GATH_VALUE contains a string value, and a pointer (for making a linked
  32. // list). A GATH_FIELD contains information to produce a data GATH_VALUE (data
  33. // source, format string and a list of values representing data points).
  34. //
  35. // The GATH_LINESPEC object contains the specification for a line of data.
  36. // It has a list of fields (one for each column), a next pointer (to allow for
  37. // a list of linespecs). It also has an enumerated class - if this lists a
  38. // WBEM class to enumerate, then a different sub-list of linespecs will be
  39. // repeated for each instance of the WBEM class. GATH_LINE stores the results
  40. // of a refresh on a line - a list of values (one for each column).
  41. //=============================================================================
  42. //-----------------------------------------------------------------------------
  43. // Constants used in the data gathering files.
  44. //-----------------------------------------------------------------------------
  45. #define NODE_KEYWORD "node"
  46. #define COLUMN_KEYWORD "columns"
  47. #define LINE_KEYWORD "line"
  48. #define ENUMLINE_KEYWORD "enumlines"
  49. #define FIELD_KEYWORD "field"
  50. #define STATIC_SOURCE "static"
  51. #define TEMPLATE_FILE_TAG "MSINFO,0000"
  52. #define SORT_VALUE "VALUE"
  53. #define SORT_LEXICAL "LEXICAL"
  54. #define COMPLEXITY_ADVANCED "ADVANCED"
  55. #define COMPLEXITY_BASIC "BASIC"
  56. #define DEPENDENCY_JOIN "dependency"
  57. #define SQL_FILTER "WQL:"
  58. //-----------------------------------------------------------------------------
  59. // These structures are used by the INTERNAL_CATEGORY structure to store both
  60. // the specification for what information is shown as well as the actually
  61. // data to be shown (refreshed on command).
  62. //-----------------------------------------------------------------------------
  63. // GATH_VALUE is used to store a list of strings. A list of column names or a
  64. // list of arguments would use the GATH_VALUE struct. Note, a next pointer is
  65. // not needed because these structures will be allocated contiguously (in
  66. // an array).
  67. struct GATH_VALUE
  68. {
  69. GATH_VALUE();
  70. ~GATH_VALUE();
  71. CString m_strText;
  72. DWORD m_dwValue;
  73. GATH_VALUE * m_pNext;
  74. };
  75. // A GATH_FIELD is used to store the specification for a text string. It contains
  76. // a format string (a printf style string) and a GATH_VALUE pointer to a list of
  77. // arguments for the format string.
  78. struct GATH_FIELD
  79. {
  80. GATH_FIELD();
  81. ~GATH_FIELD();
  82. CString m_strSource; // WBEM class containing information
  83. CString m_strFormat; // printf-type format string
  84. unsigned short m_usWidth; // width (if this field is for a column)
  85. MSIColumnSortType m_sort; // how to sort this column
  86. DataComplexity m_datacomplexity; // is this column BASIC or ADVANCED
  87. GATH_VALUE * m_pArgs; // arguments for m_strFormat
  88. GATH_FIELD * m_pNext; // next field in the list
  89. };
  90. // A GATH_LINESPEC is used to specify what is shown on a line in the listview. It
  91. // contains a string for a class to enumerate. If this string is empty, then
  92. // the struct merely represents a single line in the display. The GATH_FIELD pointer
  93. // is to a list of the fields (one for each column), and the m_pNext pointer is
  94. // to the next line to be displayed. If m_strEnumerateClass is not empty, then
  95. // the class specified is enumerated, and the lines pointed to by m_pEnumeratedGroup
  96. // are repeated for each instance of the class. Note, if a class is to be enumerated,
  97. // the m_pFields pointer must be null (since this line won't display anything
  98. // itself, but enumerate a class for another group of lines).
  99. //
  100. // m_pConstraintFields is a pointer to a linked list of fields which serve as
  101. // constraints for the enumeration. These can be used to filter the enumerated
  102. // instances or to perform joins to related classes so they are enumerated as
  103. // well is the primary class. m_pConstraintFields should only be non-NULL when
  104. // m_pEnumeratedGroup is non-NULL.
  105. struct GATH_LINESPEC
  106. {
  107. GATH_LINESPEC();
  108. ~GATH_LINESPEC();
  109. CString m_strEnumerateClass;
  110. DataComplexity m_datacomplexity;
  111. GATH_FIELD * m_pFields;
  112. GATH_LINESPEC * m_pEnumeratedGroup;
  113. GATH_FIELD * m_pConstraintFields;
  114. GATH_LINESPEC * m_pNext;
  115. };
  116. // The GATH_LINE struct contains the actual data to be displayed on a line. The
  117. // refresh operation will take list of GATH_LINESPEC structs and create a list
  118. // of GATH_LINE structs. The m_aValue pointer is to a list of values to be
  119. // displayed (one per column).
  120. struct GATH_LINE
  121. {
  122. GATH_LINE();
  123. ~GATH_LINE();
  124. GATH_VALUE * m_aValue;
  125. DataComplexity m_datacomplexity;
  126. };
  127. //-----------------------------------------------------------------------------
  128. // The following structure is used within this object to store information
  129. // about the categories. Specifically, this structure will be allocated for
  130. // each category, and a pointer stored in m_mapCategories. This representation
  131. // will not be used outside this object, rather, a CDataCategory object will
  132. // be used.
  133. //-----------------------------------------------------------------------------
  134. struct INTERNAL_CATEGORY
  135. {
  136. INTERNAL_CATEGORY();
  137. ~INTERNAL_CATEGORY();
  138. GATH_VALUE m_categoryName; // realized name of category
  139. GATH_FIELD m_fieldName; // field used to get name
  140. CString m_strEnumerateClass; // if !(empty or "static"), this category repeated
  141. CString m_strIdentifier; // non-localized internal name
  142. CString m_strNoInstances; // message to use if there are no instances
  143. BOOL m_fListView; // is this cat a list view
  144. BOOL m_fDynamic; // was this cat enumerated
  145. BOOL m_fIncluded; // should this cat be included
  146. DWORD m_dwID; // the ID for this cat
  147. DWORD m_dwParentID; // my parent
  148. DWORD m_dwChildID; // my first child
  149. DWORD m_dwDynamicChildID; // my first dynamically created child
  150. DWORD m_dwNextID; // my next sibling
  151. DWORD m_dwPrevID; // my previous sibling
  152. DWORD m_dwColCount; // number of columns
  153. GATH_FIELD * m_pColSpec; // list of fields to make col names
  154. GATH_VALUE * m_aCols; // realized list of columns
  155. GATH_LINESPEC* m_pLineSpec; // list of line specifiers
  156. DWORD m_dwLineCount; // number of lines (NOT number of line specs)
  157. GATH_LINE * * m_apLines; // realized list of lines
  158. BOOL m_fRefreshed; // has the category ever been refreshed
  159. DWORD m_dwLastError; // last error specific to this category
  160. // DEBUG dump functions to sanity check the internal structure.
  161. #if _DEBUG
  162. void DumpCategoryRecursive(int iIndent, CDataGatherer * pGatherer);
  163. CString DumpField(GATH_FIELD * pField);
  164. CString DumpLineSpec(GATH_LINESPEC * pLineSpec, CString strIndent);
  165. CString DumpLine(GATH_LINE * pLine, DWORD nColumns);
  166. #endif
  167. };
  168. //-----------------------------------------------------------------------------
  169. // The CEnumMap is a utility class to cache IEnumWbemClassObject pointers.
  170. // There will be one instance of this class used to improve performance
  171. // by avoiding the high overhead associated with creating enumerators for
  172. // certain classes.
  173. //-----------------------------------------------------------------------------
  174. class IEnumWbemClassObject;
  175. class CEnumMap
  176. {
  177. public:
  178. CEnumMap() { };
  179. ~CEnumMap() { Reset(); };
  180. IEnumWbemClassObject * GetEnumerator(const CString & strClass);
  181. void SetEnumerator(const CString & strClass, IEnumWbemClassObject * pEnum);
  182. void Reset();
  183. private:
  184. CMapStringToPtr m_mapEnum;
  185. };
  186. //-----------------------------------------------------------------------------
  187. // The CDataProvider class implements the object which actually goes and
  188. // retrieves the information. Currently, it uses WBEM to accomplish this.
  189. // At this time there will only be one CDataProvider object, and the
  190. // CDataGatherer object will be used to retrieve a pointer to it.
  191. //-----------------------------------------------------------------------------
  192. class IWbemClassObject;
  193. class IEnumWbemClassObject;
  194. class IWbemServices;
  195. class CMSIObject;
  196. class CMSIEnumerator;
  197. class CDataProvider
  198. {
  199. friend class CMSIEnumerator;
  200. public:
  201. typedef enum { MOS_NO_INSTANCES, MOS_MSG_INSTANCE, MOS_INSTANCE } MSIObjectState;
  202. public:
  203. CDataProvider();
  204. ~CDataProvider();
  205. // Create the provider for the specifier computer. If there are problems
  206. // connecting to WBEM pGatherer->SetLastError will be called to explain.
  207. BOOL Create(const CString & strComputer, CDataGatherer * pGatherer);
  208. // Query a value from the provider. Currently supports string, date/time and DWORD values.
  209. BOOL QueryValue(const CString & strClass, const CString & strProperty, CString & strResult);
  210. BOOL QueryValueDWORD(const CString & strClass, const CString & strProperty, DWORD & dwResult, CString & strMessage);
  211. BOOL QueryValueDateTime(const CString & strClass, const CString & strProperty, COleDateTime & datetime, CString & strMessage);
  212. BOOL QueryValueDoubleFloat(const CString & strClass, const CString & strProperty, double & dblResult, CString & strMessage);
  213. // ResetClass causes the enumeration of a WBEM class to reset to the first instance.
  214. // EnumClass advances the class to the next instance. ClearCache empties out the
  215. // internal class to interface pointer cache.
  216. BOOL ResetClass(const CString & strClass, const GATH_FIELD * pConstraints);
  217. BOOL EnumClass(const CString & strClass, const GATH_FIELD * pConstraints);
  218. void ClearCache();
  219. CString m_strTrue; // cached string value for "TRUE"
  220. CString m_strFalse; // cached string value for "FALSE"
  221. CString m_strBadProperty; // shown if Get fails
  222. CString m_strPropertyUnavail; // shown if VariantChange failes
  223. CString m_strComputer; // computer name for this provider
  224. CString m_strAccessDeniedLabel; // shown for WBEM access denied
  225. CString m_strTransportFailureLabel; // shown for WBEM transport failure
  226. CEnumMap m_enumMap; // caches WBEM interface pointers for enumerators
  227. DWORD m_dwRefreshingCategoryID; // the CDataGatherer ID for the refreshing category - used to set errors
  228. private:
  229. BOOL m_fInitialized; // has Create been called and succeeded
  230. IWbemServices * m_pIWbemServices; // saved WBEM services pointer
  231. CMapStringToPtr m_mapNamespaceToService; // has WBEM services pointers for other namespaces
  232. CDataGatherer * m_pGatherer;
  233. // We keep two caches around - one is from class name to enumerator interface,
  234. // the other from class name to object interface.
  235. CMapStringToPtr m_mapClassToInterface;
  236. CMapStringToPtr m_mapClassToEnumInterface;
  237. // The third cache serves a rather kludgy purpose - if a class name is
  238. // contained in it, then that class must have at least one instance
  239. // enumerated for it, even if it is an artificially generated empty instance.
  240. // This is useful for nested enumlines with SQL statements.
  241. CMapStringToPtr m_mapEnumClassMinOfOne;
  242. // Get or remove the object or enumerator object from the cache. Note that
  243. // GetObject will enumerate the next instance of the associated enumerator.
  244. IWbemServices * GetWBEMService(CString * pstrNamespace = NULL);
  245. CMSIEnumerator * GetEnumObject(const CString & strClass, const GATH_FIELD * pConstraints = NULL);
  246. CMSIObject * GetObject(const CString & strClass, const GATH_FIELD * pConstraints, CString * pstrLabel = NULL);
  247. void RemoveEnumObject(const CString & strClass);
  248. void RemoveObject(const CString & strClass);
  249. // This function is used to look up a string in a value map (to get localized enumerated strings.
  250. HRESULT CheckValueMap(const CString& strClass, const CString& strProperty, const CString& strVal, CString &strResult);
  251. // Evaluate whether the current object satisfies a filter (a static constraint).
  252. BOOL IsDependencyJoin(const GATH_FIELD * pConstraints);
  253. void EvaluateDependencyJoin(IWbemClassObject * pObject);
  254. BOOL EvaluateFilter(IWbemClassObject * pObject, const GATH_FIELD * pConstraints);
  255. void EvaluateJoin(const CString & strClass, IWbemClassObject * pObject, const GATH_FIELD * pConstraints);
  256. };
  257. //-----------------------------------------------------------------------------
  258. // The CMSIObject class is a thin wrapper for the IWbemClassObject interface.
  259. // We use this so we can return a custom label for a null object (if there
  260. // are no instances, we sometimes want to show some caption).
  261. //-----------------------------------------------------------------------------
  262. class IWbemClassObject;
  263. class CMSIObject
  264. {
  265. public:
  266. CMSIObject(IWbemClassObject * pObject, const CString & strLabel, HRESULT hres, CDataProvider * pProvider, CDataProvider::MSIObjectState objState);
  267. ~CMSIObject();
  268. HRESULT Get(BSTR property, LONG lFlags, VARIANT *pVal, VARTYPE *pvtType, LONG *plFlavor);
  269. HRESULT GetErrorLabel(CString & strError);
  270. CDataProvider::MSIObjectState IsValid();
  271. private:
  272. IWbemClassObject * m_pObject;
  273. CString m_strLabel;
  274. HRESULT m_hresCreation;
  275. CDataProvider * m_pProvider;
  276. CDataProvider::MSIObjectState m_objState;
  277. };
  278. //-----------------------------------------------------------------------------
  279. // The CMSIEnumerator class encapsulates the WBEM enumerator interface, or
  280. // implements our own form of enumerator (such as for the LNK command in the
  281. // template file).
  282. //-----------------------------------------------------------------------------
  283. class IEnumWbemClassObject;
  284. class CMSIEnumerator
  285. {
  286. public:
  287. CMSIEnumerator();
  288. ~CMSIEnumerator();
  289. HRESULT Create(const CString & strClass, const GATH_FIELD * pConstraints, CDataProvider * pProvider);
  290. HRESULT Next(CMSIObject ** ppObject);
  291. HRESULT Reset(const GATH_FIELD * pConstraints);
  292. private:
  293. typedef enum { CLASS, WQL, LNK, INTERNAL } EnumType;
  294. private:
  295. EnumType m_enumtype;
  296. BOOL m_fOnlyDups;
  297. BOOL m_fGotDuplicate;
  298. BOOL m_fMinOfOne;
  299. int m_iMinOfOneCount;
  300. CString m_strClass;
  301. CString m_strObjPath;
  302. CString m_strAssocClass;
  303. CString m_strResultClass;
  304. CString m_strLNKObject;
  305. CString m_strNoInstanceLabel;
  306. IEnumWbemClassObject * m_pEnum;
  307. CDataProvider * m_pProvider;
  308. const GATH_FIELD * m_pConstraints;
  309. HRESULT m_hresCreation;
  310. IWbemClassObject * m_pSavedDup;
  311. CString m_strSavedDup;
  312. CStringList * m_pstrList;
  313. private:
  314. BOOL AssocObjectOK(IWbemClassObject * pObject, CString & strAssociatedObject);
  315. HRESULT ParseLNKCommand(const CString & strStatement, CString & strObjPath, CString & strAssocClass, CString & strResultClass);
  316. void ProcessEnumString(CString & strStatement, BOOL & fMinOfOne, BOOL & fOnlyDups, CDataProvider * pProvider, CString & strNoInstanceLabel, BOOL fMakeDoubleBackslashes = FALSE);
  317. HRESULT CreateInternalEnum(const CString & strInternal, CDataProvider * pProvider);
  318. HRESULT InternalNext(IWbemClassObject ** ppWBEMObject);
  319. };
  320. //-----------------------------------------------------------------------------
  321. // Privately used functions. Encapsulated into classes so they will be easy
  322. // to make friends of the CDataGatherer class. Documentation for these
  323. // functions can be found with their implementations.
  324. //-----------------------------------------------------------------------------
  325. class CTemplateFileFunctions
  326. {
  327. public:
  328. static BOOL ReadTemplateFile(CFile *pFile, CDataGatherer *pGatherer);
  329. static BOOL ReadHeaderInfo(CFile *pFile, CDataGatherer *pGatherer);
  330. static DWORD ReadNodeRecursive(CFile *pFile, CDataGatherer *pGatherer, DWORD dwParentID, DWORD dwPrevID);
  331. static BOOL VerifyAndAdvanceFile(CFile * pFile, const CString &strVerify);
  332. static BOOL VerifyUNICODEFile(CFile *pFile);
  333. static DWORD CreateCategory(CDataGatherer * pGatherer, DWORD dwParentID, DWORD dwPrevID);
  334. static BOOL GetKeyword(CFile * pFile, CString & strKeyword);
  335. static BOOL ReadColumnInfo(CFile * pFile, CDataGatherer * pGatherer, DWORD dwID);
  336. static GATH_LINESPEC * ReadLineInfo(CFile * pFile, CDataGatherer * pGatherer);
  337. static GATH_LINESPEC * ReadLineEnumRecursive(CFile * pFile, CDataGatherer * pGatherer);
  338. static BOOL ReadArgument(CFile * pFile, CString & strSource);
  339. static BOOL ReadField(CFile * pFile, GATH_FIELD & field);
  340. static BOOL LoadTemplateDLLs(HKEY hkeyBase, CDataGatherer * pGatherer);
  341. static BOOL ApplyCategories(const CString & strCategories, CDataGatherer * pGatherer);
  342. static BOOL RecurseTreeCategories(BOOL fParentOK, DWORD dwID, const CString & strCategories, CDataGatherer * pGatherer);
  343. static void RemoveExtraCategories(DWORD dwID, CDataGatherer * pGatherer);
  344. };
  345. class CRefreshFunctions
  346. {
  347. public:
  348. static BOOL RefreshValue(CDataGatherer * pGatherer, GATH_VALUE * pVal, GATH_FIELD * pField);
  349. static BOOL RefreshColumns(CDataGatherer * pGatherer, INTERNAL_CATEGORY * pInternal);
  350. static BOOL RefreshLines(CDataGatherer * pGatherer, GATH_LINESPEC * pLineSpec, DWORD dwColumns, CPtrList & listLinePtrs, volatile BOOL * pfCancel = NULL);
  351. static BOOL RefreshOneLine(CDataGatherer * pGatherer, GATH_LINE * pLine, GATH_LINESPEC * pLineSpec, DWORD dwColCount);
  352. static BOOL GetValue(CDataGatherer *pGatherer, TCHAR cFormat, TCHAR *szFormatFragment, CString &strResult, DWORD &dwResult, GATH_FIELD *pField, int iArgNumber);
  353. };
  354. //-----------------------------------------------------------------------------
  355. // Utility functions.
  356. //-----------------------------------------------------------------------------
  357. void GetToken(CString & strToken, CString & strString, TCHAR cDelimiter);