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.

312 lines
9.6 KiB

  1. // compkey.h: interface for the CCompoundKey class
  2. // Copyright (c)1997-2001 Microsoft Corporation
  3. //
  4. //////////////////////////////////////////////////////////////////////
  5. #if _MSC_VER >= 1000
  6. #pragma once
  7. #endif // _MSC_VER >= 1000
  8. /*
  9. Class description
  10. Naming:
  11. CCompoundKey stands for a key that is compounded by many properties.
  12. Base class:
  13. None. This is not a class that implements a WMI class.
  14. It is not derived from CGenericClass.
  15. Purpose of class:
  16. (1) Comparing two instances of the same WMI class is not an easy job because
  17. most of time we need to look up an instance based on its key. Ideally, if
  18. WMI provides some canonical name, it will be very easy. The closest thing
  19. WMI gives us regarding the identify of instance is the instance path.
  20. But WMI gives inconsistent paths for the same instance. At least, we've
  21. found that if a boolean property is part of the key, then sometimes WMI
  22. gives its path containing a string portion like "BoolPropName=1" and other
  23. times (for the same instance) it gives "BoolPropName=TRUE". For this reason,
  24. we are forced to create a robust identify lookup mechanism.
  25. (2) This class serves two purposes:
  26. (a) the key for our map of instance lookup. Potentially, we may have tens of
  27. thousands of instances (like random ports). We need an efficient way to
  28. find an instance.
  29. (b) provide access (GetPropertyValue) for key properties of an instance.
  30. (3) This is part of the effort to implement another open extension model (embedding)
  31. Design:
  32. (1) We only store the key property's values (m_pValues). In other words, we rely
  33. on user to know the order properties are put into the class. The reasons for
  34. this design are:
  35. (a) Efficiency.
  36. (b) Don't want to store the property names because one class only needs one
  37. copy of the property names.
  38. (c) For each embedded class, we already have to find out all its key property names.
  39. Use:
  40. (1) Create an instance. Our constructor strictly requires the count for key properties
  41. at construction time. This is because you have to know each class (and their key
  42. property names, even the names particular order) at this point.
  43. (2) Call AddKeyPropertyValue to add a property value. Please note: for efficiency reasons,
  44. the variant pointer passed into the call is owned by this class (so that no copy needs
  45. to be made).
  46. (3) most likely, you will add this newly created instance to a map.
  47. */
  48. class CCompoundKey
  49. {
  50. public:
  51. CCompoundKey(DWORD dwSize);
  52. ~CCompoundKey();
  53. HRESULT AddKeyPropertyValue (DWORD dwIndex, VARIANT** ppVar);
  54. bool operator < (const CCompoundKey& right)const;
  55. HRESULT GetPropertyValue (DWORD dwIndex, VARIANT* pVar)const;
  56. protected:
  57. int CompareVariant (VARIANT* pVar1, VARIANT* pVar2)const;
  58. VARIANT** m_pValues;
  59. DWORD m_dwSize;
  60. };
  61. //=========================================================================
  62. /*
  63. Class description
  64. Naming:
  65. CompKeyLessThan.
  66. Base class:
  67. None.
  68. Purpose of class:
  69. (1) This is the functor for our map that uses CCompoundKey as key.
  70. Design:
  71. (1) Just one operator ()
  72. Use:
  73. (1) Give it to the map's comparison parameter.
  74. */
  75. struct CompKeyLessThan
  76. {
  77. bool operator()( const CCompoundKey* pX, const CCompoundKey* pY ) const;
  78. };
  79. //=========================================================================
  80. //
  81. // declarations for the ease of use for maps using CCompoundKey
  82. //
  83. typedef std::map<CCompoundKey*, DWORD, CompKeyLessThan > MapExtClassCookie;
  84. typedef MapExtClassCookie::iterator ExtClassCookieIterator;
  85. //=========================================================================
  86. //
  87. // forward declaration for the use in CExtClassInstCookieList
  88. //
  89. class CSceStore;
  90. //=========================================================================
  91. /*
  92. Class description
  93. Naming:
  94. CExtClassInstCookieList.
  95. Base class:
  96. None.
  97. Purpose of class:
  98. (1) To support multiple instance persistence, we need a mechanism to tell
  99. instances apart in the persistence store. Due to the limitations of INF
  100. format file API, this is not an easy job. All instances of a particular
  101. class must be written into one section of the INF file. We have absolutely
  102. no control as what order the key=value pair will be written. To make things
  103. worse, the key in the key=value pair is not allowed to repeat. In other
  104. words, if we don't know anything, we can only persist one single instance.
  105. To solve this problem, we invent the notation of cookies for instances.
  106. For each class (and thus a section bearing the class's name), we have
  107. cookie arrays in the following form (the numbers are cookies):
  108. A1 = 12 : 2 : 3 : 6 :
  109. A2 = 1 : 5 : 8 : 10 : 24 : 112233 : 7 :
  110. For a particular instance, it is associated with a cookie. In order for us
  111. to persist or read an instance's properties, we must obtain the cookie, say, 5.
  112. Then all key properties of this instance is saved in the value of
  113. K5 = value
  114. and all non-key properties are all saved in
  115. 5PropertyName = value
  116. Design:
  117. (1) Instancce lookup (given a compound key CCompoundKey to find its cookie) must
  118. efficient. So, a map is used (m_mapCookies).
  119. (2) We want to control the order an instance is used. Map doesn't work well in this
  120. case. So, we create a vector (m_vecCookies) to link cookies back to its compound key.
  121. This way when the access starts, we can traverse the vector using index.
  122. (3) We don't want to blindly continue to look for cookie arrays (A1, A2, etc.) when we
  123. need to create the cookie list for a particular class. And we don't want to
  124. write one cookie array to be so long that it is very hard to read. So, we adopt
  125. a strategy that we increment the A_i count and continue try to read A_(i+1) only
  126. if A_i exists. But then, if instances are deleted, we will need to have less cookie
  127. arrays. To know how many cookie arrays were read out (and potentially remove the
  128. unwanted ones when updating the store with the new cookie list), we have m_dwCookieArrayCount.
  129. (4) New cookie are assign by increment the current maximum cookie m_dwMaxCookie. To avoid
  130. DWORD overflow, we also have a function (GetNextFreeCookie) to look fora newer cookie
  131. when the 0xFFFFFFFFF is already used.
  132. (5) We also defined a cookie called INVALID_COOKIE = 0.
  133. Use:
  134. (1) Instantiate an instance of the class.
  135. (2) Call Create function to populate its contents.
  136. (3) Ready for your use.
  137. */
  138. class CExtClassInstCookieList
  139. {
  140. public:
  141. CExtClassInstCookieList();
  142. ~CExtClassInstCookieList();
  143. HRESULT Create(
  144. CSceStore* pSceStore,
  145. LPCWSTR pszSectionName,
  146. std::vector<BSTR>* pvecNames
  147. );
  148. HRESULT Save(
  149. CSceStore* pSceStore,
  150. LPCWSTR pszSectionName
  151. );
  152. DWORD GetCompKeyCookie(
  153. LPCWSTR pszComKey,
  154. ExtClassCookieIterator* pIt
  155. );
  156. HRESULT AddCompKey(
  157. LPCWSTR pszCompKey,
  158. DWORD dwDefCookie,
  159. DWORD *pdwNewCookie
  160. );
  161. DWORD RemoveCompKey(
  162. CSceStore* pSceStore,
  163. LPCWSTR pszSectionName,
  164. LPCWSTR pszCompKey
  165. );
  166. HRESULT Next(
  167. BSTR* pbstrCompoundKey,
  168. DWORD* pdwCookie,
  169. DWORD* pdwResumeHandle
  170. );
  171. //
  172. // return the count of cookies
  173. //
  174. DWORD
  175. GetCookieCount ()
  176. {
  177. return m_vecCookies.size();
  178. }
  179. private:
  180. HRESULT DeleteKeyFromStore(
  181. CSceStore* pSceStore,
  182. LPCWSTR pszSectionName,
  183. DWORD dwCookie
  184. );
  185. HRESULT GetNextFreeCookie(
  186. DWORD* pdwCookie
  187. );
  188. HRESULT CreateCompoundKeyFromString(
  189. LPCWSTR pszCompKeyStr,
  190. CCompoundKey** ppCompKey
  191. );
  192. HRESULT CreateCompoundKeyString(
  193. BSTR* pbstrCompKey,
  194. const CCompoundKey* pKey
  195. );
  196. void Cleanup();
  197. DWORD m_dwMaxCookie;
  198. MapExtClassCookie m_mapCookies;
  199. //
  200. // memories (pKey) is not managed by this struct CookieKeyPair
  201. // pKey is taken care of somewhere else (actually m_mapCookies does it)
  202. //
  203. struct CookieKeyPair
  204. {
  205. DWORD dwCookie;
  206. CCompoundKey* pKey;
  207. };
  208. typedef std::vector<CookieKeyPair*> CookieKeyVector;
  209. typedef CookieKeyVector::iterator CookieKeyIterator;
  210. CookieKeyVector m_vecCookies;
  211. std::vector<BSTR>* m_pVecNames;
  212. DWORD m_dwCookieArrayCount;
  213. };