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.

461 lines
13 KiB

  1. /*--------------------------------------------------------------------------*
  2. *
  3. * Microsoft Windows
  4. * Copyright (C) Microsoft Corporation, 1992 - 1999
  5. *
  6. * File: strtable.h
  7. *
  8. * Contents: Interface file for CStringTable
  9. *
  10. * History: 25-Jun-98 jeffro Created
  11. *
  12. *--------------------------------------------------------------------------*/
  13. #ifndef STRTABLE_H
  14. #define STRTABLE_H
  15. #pragma once
  16. #include <exception> // for class exception
  17. #include <string> // for string relational operators
  18. #include "guidhelp.h" // for GUID relational operators
  19. #include "stgio.h"
  20. #include "strings.h"
  21. #ifdef DBG
  22. #define DECLARE_DIAGNOSITICS() \
  23. public: void Dump() const;
  24. #else
  25. #define DECLARE_DIAGNOSITICS() \
  26. public: void Dump() const {}
  27. #endif
  28. #ifdef DBG
  29. extern CTraceTag tagStringTable;
  30. #endif // DBG
  31. /*--------------------------------------------------------------------------
  32. * IdentifierRange should be private to CIdentifierPool, but
  33. * compiler bugs prevent it.
  34. */
  35. template<class T>
  36. class IdentifierRange
  37. {
  38. public:
  39. IdentifierRange(T idMin_ = T(), T idMax_ = T())
  40. : idMin (idMin_), idMax (idMax_)
  41. { ASSERT (idMin <= idMax); }
  42. bool operator== (const IdentifierRange<T>& other) const
  43. { return ((idMin == other.idMin) && (idMax == other.idMax)); }
  44. bool operator!= (const IdentifierRange<T>& other) const
  45. { return (!(*this == other.idMin)); }
  46. T idMin;
  47. T idMax;
  48. };
  49. template<class T = int>
  50. class CIdentifierPool : public CXMLObject
  51. {
  52. public:
  53. typedef IdentifierRange<T> Range;
  54. typedef std::list<Range> RangeList;
  55. private:
  56. friend IStream& operator>> (IStream& stm, CIdentifierPool<T>& pool);
  57. friend IStream& operator<< (IStream& stm, const CIdentifierPool<T>& pool);
  58. virtual void Persist(CPersistor &persistor);
  59. DEFINE_XML_TYPE(XML_TAG_IDENTIFIER_POOL);
  60. SC ScInvertRangeList (RangeList& rlInvert) const;
  61. #ifdef DBG
  62. void DumpRangeList (const RangeList& l) const;
  63. #endif
  64. public:
  65. DECLARE_DIAGNOSITICS();
  66. CIdentifierPool (T idMin, T idMax);
  67. CIdentifierPool (IStream& stm);
  68. T Reserve();
  69. bool Release(T idRelease);
  70. bool IsValid () const;
  71. bool IsRangeListValid (const RangeList& rl) const;
  72. SC ScGenerate (const RangeList& rlUsedIDs);
  73. static bool AddToRangeList (RangeList& rl, const Range& rangeToAdd);
  74. static bool AddToRangeList (RangeList& rl, T idAdd);
  75. class pool_exhausted : public exception
  76. {
  77. public:
  78. pool_exhausted(const char *_S = "pool exhausted") _THROW0()
  79. : exception(_S) {}
  80. virtual ~pool_exhausted() _THROW0()
  81. {}
  82. };
  83. private:
  84. RangeList m_AvailableIDs;
  85. RangeList m_StaleIDs;
  86. T m_idAbsoluteMin;
  87. T m_idAbsoluteMax;
  88. T m_idNextAvailable;
  89. };
  90. typedef CIdentifierPool<MMC_STRING_ID> CStringIDPool;
  91. /*--------------------------------------------------------------------------
  92. * CEntry and CStoredEntry should be private to CStringTable,
  93. * but compiler bugs prevent it.
  94. */
  95. /*
  96. * represents a string table entry in memory
  97. */
  98. class CEntry : public CXMLObject
  99. {
  100. friend class CStringTable;
  101. friend class CStringEnumerator;
  102. friend struct CompareEntriesByID;
  103. friend struct CompareEntriesByString;
  104. friend struct IdentifierReleaser;
  105. friend IStream& operator>> (IStream& stm, CEntry& entry);
  106. friend IStream& operator<< (IStream& stm, const CEntry& entry);
  107. public:
  108. DECLARE_DIAGNOSITICS();
  109. CEntry () : m_id(0), m_cRefs(0) {}
  110. CEntry (const std::wstring& str, MMC_STRING_ID id)
  111. : m_str(str), m_id(id), m_cRefs(0)
  112. {}
  113. virtual LPCTSTR GetXMLType() {return XML_TAG_STRING_TABLE_STRING;}
  114. virtual void Persist(CPersistor& persistor);
  115. private:
  116. /*
  117. * This ctor is only used by CStringTable when reconstructing
  118. * the entry from a file.
  119. */
  120. CEntry (const std::wstring& str, MMC_STRING_ID id, DWORD cRefs)
  121. : m_str(str) , m_id(id), m_cRefs(cRefs)
  122. {}
  123. private:
  124. bool operator< (const LPCWSTR psz) const
  125. { return (m_str < psz); }
  126. bool operator< (const CEntry& other) const
  127. { return (m_str < other.m_str); }
  128. bool operator== (const LPCWSTR psz) const
  129. { return (m_str == psz); }
  130. bool operator== (const CEntry& other) const
  131. { return (m_str == other.m_str); }
  132. //private:
  133. public: // temp!
  134. std::wstring m_str;
  135. MMC_STRING_ID m_id;
  136. DWORD m_cRefs;
  137. };
  138. struct CompareEntriesByID :
  139. public std::binary_function<const CEntry&, const CEntry&, bool>
  140. {
  141. bool operator() (const CEntry& entry1, const CEntry& entry2) const
  142. { return (entry1.m_id < entry2.m_id); }
  143. };
  144. struct CompareEntriesByString :
  145. public std::binary_function<const CEntry&, const CEntry&, bool>
  146. {
  147. bool operator() (const CEntry& entry1, const CEntry& entry2) const
  148. { return (entry1 < entry2); }
  149. };
  150. struct IdentifierReleaser :
  151. public std::unary_function<CEntry&, bool>
  152. {
  153. IdentifierReleaser (CStringIDPool& pool) : m_pool (pool) {}
  154. bool operator() (CEntry& entry) const
  155. { return (m_pool.Release (entry.m_id)); }
  156. private:
  157. CStringIDPool& m_pool;
  158. };
  159. /*
  160. * Because the string and ID indexes map their keys to CEntry
  161. * pointers, we must use a collection that doesn't move its
  162. * elements once they're inserted. The only STL collection
  163. * that meets this requirement is a list.
  164. */
  165. typedef std::list<CEntry> EntryList;
  166. typedef XMLListCollectionWrap<EntryList> CStringTable_base;
  167. class CStringTable : public CStringTable_base
  168. {
  169. friend IStream& operator>> (IStream& stm, CStringTable& entry);
  170. friend IStream& operator<< (IStream& stm, const CStringTable& entry);
  171. public:
  172. DECLARE_DIAGNOSITICS();
  173. CStringTable (CStringIDPool* pIDPool);
  174. CStringTable (CStringIDPool* pIDPool, IStream& stm);
  175. ~CStringTable ();
  176. CStringTable (const CStringTable& other);
  177. CStringTable& operator= (const CStringTable& other);
  178. /*
  179. * IStringTable methods. Note that object doesn't implement
  180. * IStringTable, because IUnknown isn't implemented.
  181. */
  182. STDMETHOD(AddString) (LPCOLESTR pszAdd, MMC_STRING_ID* pID);
  183. STDMETHOD(GetString) (MMC_STRING_ID id, ULONG cchBuffer, LPOLESTR lpBuffer, ULONG* pcchOut) const;
  184. STDMETHOD(GetStringLength) (MMC_STRING_ID id, ULONG* pcchString) const;
  185. STDMETHOD(DeleteString) (MMC_STRING_ID id);
  186. STDMETHOD(DeleteAllStrings) ();
  187. STDMETHOD(FindString) (LPCOLESTR pszFind, MMC_STRING_ID* pID) const;
  188. STDMETHOD(Enumerate) (IEnumString** ppEnum) const;
  189. size_t size() const
  190. { return (m_Entries.size()); }
  191. virtual void Persist(CPersistor& persistor)
  192. {
  193. CStringTable_base::Persist(persistor);
  194. if (persistor.IsLoading())
  195. IndexAllEntries ();
  196. }
  197. SC ScCollectInUseIDs (CStringIDPool::RangeList& l) const;
  198. private:
  199. void IndexAllEntries ()
  200. { IndexEntries (m_Entries.begin(), m_Entries.end()); }
  201. void IndexEntries (EntryList::iterator first, EntryList::iterator last)
  202. {
  203. for (; first != last; ++first)
  204. IndexEntry (first);
  205. }
  206. void IndexEntry (EntryList::iterator);
  207. typedef std::map<std::wstring, EntryList::iterator> StringToEntryMap;
  208. typedef std::map<MMC_STRING_ID, EntryList::iterator> IDToEntryMap;
  209. EntryList::iterator LookupEntryByString (const std::wstring&) const;
  210. EntryList::iterator LookupEntryByID (MMC_STRING_ID) const;
  211. EntryList::iterator FindInsertionPointForEntry (const CEntry& entry) const;
  212. #ifdef DBG
  213. static void AssertValid (const CStringTable* pTable);
  214. #define ASSERT_VALID_(p) do { AssertValid(p); } while(0)
  215. #else
  216. #define ASSERT_VALID_(p) ((void) 0)
  217. #endif
  218. private:
  219. EntryList m_Entries;
  220. StringToEntryMap m_StringIndex;
  221. IDToEntryMap m_IDIndex;
  222. CStringIDPool* m_pIDPool;
  223. };
  224. extern const CLSID CLSID_MMC;
  225. /*+-------------------------------------------------------------------------*
  226. * class CLSIDToStringTableMap
  227. *
  228. *
  229. * PURPOSE: stl::map derived class that maps snapin_clsid to stringtable
  230. * and supports XML persistence of the map collection
  231. *
  232. * NOTE: Throws exceptions!
  233. *+-------------------------------------------------------------------------*/
  234. typedef std::map<CLSID, CStringTable> ST_base;
  235. class CLSIDToStringTableMap : public XMLMapCollection<ST_base>
  236. {
  237. public:
  238. // this method is provided as alternative to Persist, whic allows
  239. // to cache parameter to be used to create new string tables
  240. void PersistSelf(CStringIDPool *pIDPool, CPersistor& persistor)
  241. {
  242. m_pIDPersistPool = pIDPool;
  243. persistor.Persist(*this, NULL);
  244. }
  245. protected:
  246. // XML persistence implementation
  247. virtual LPCTSTR GetXMLType() {return XML_TAG_STRING_TABLE_MAP;}
  248. virtual void OnNewElement(CPersistor& persistKey,CPersistor& persistVal)
  249. {
  250. CLSID key;
  251. ZeroMemory(&key,sizeof(key));
  252. persistKey.Persist(key);
  253. CStringTable val(m_pIDPersistPool);
  254. persistVal.Persist(val);
  255. insert(ST_base::value_type(key,val));
  256. }
  257. private:
  258. CStringIDPool *m_pIDPersistPool;
  259. };
  260. typedef CLSIDToStringTableMap::value_type TableMapValue;
  261. class CMasterStringTable : public IStringTablePrivate, public CComObjectRoot, public CXMLObject
  262. {
  263. friend IStorage& operator>> (IStorage& stg, CMasterStringTable& mst);
  264. friend IStorage& operator<< (IStorage& stg, const CMasterStringTable& mst);
  265. public:
  266. DECLARE_DIAGNOSITICS();
  267. CMasterStringTable ();
  268. ~CMasterStringTable ();
  269. public:
  270. DEFINE_XML_TYPE(XML_TAG_MMC_STRING_TABLE);
  271. virtual void Persist(CPersistor& persistor);
  272. SC ScPurgeUnusedStrings();
  273. public:
  274. /*
  275. * ATL COM map
  276. */
  277. BEGIN_COM_MAP (CMasterStringTable)
  278. COM_INTERFACE_ENTRY (IStringTablePrivate)
  279. END_COM_MAP ()
  280. /*
  281. * IStringTablePrivate methods
  282. */
  283. STDMETHOD(AddString) (LPCOLESTR pszAdd, MMC_STRING_ID* pID, const CLSID* pclsid);
  284. STDMETHOD(GetString) (MMC_STRING_ID id, ULONG cchBuffer, LPOLESTR lpBuffer, ULONG* pcchOut, const CLSID* pclsid);
  285. STDMETHOD(GetStringLength) (MMC_STRING_ID id, ULONG* pcchString, const CLSID* pclsid);
  286. STDMETHOD(DeleteString) (MMC_STRING_ID id, const CLSID* pclsid);
  287. STDMETHOD(DeleteAllStrings) (const CLSID* pclsid);
  288. STDMETHOD(FindString) (LPCOLESTR pszFind, MMC_STRING_ID* pID, const CLSID* pclsid);
  289. STDMETHOD(Enumerate) (IEnumString** ppEnum, const CLSID* pclsid);
  290. /*
  291. * Shorthand into IStringTablePrivate (simulating a default parameter)
  292. */
  293. STDMETHOD(AddString) (LPCOLESTR pszAdd, MMC_STRING_ID* pID)
  294. { return (AddString (pszAdd, pID, &CLSID_MMC)); }
  295. STDMETHOD(GetString) (MMC_STRING_ID id, ULONG cchBuffer, LPOLESTR lpBuffer, ULONG* pcchOut)
  296. { return (GetString (id, cchBuffer, lpBuffer, pcchOut, &CLSID_MMC)); }
  297. STDMETHOD(GetStringLength) (MMC_STRING_ID id, ULONG* pcchString)
  298. { return (GetStringLength (id, pcchString, &CLSID_MMC)); }
  299. STDMETHOD(DeleteString) (MMC_STRING_ID id)
  300. { return (DeleteString (id, &CLSID_MMC)); }
  301. STDMETHOD(DeleteAllStrings) ()
  302. { return (DeleteAllStrings (&CLSID_MMC)); }
  303. STDMETHOD(FindString) (LPCOLESTR pszFind, MMC_STRING_ID* pID)
  304. { return (FindString (pszFind, pID, &CLSID_MMC)); }
  305. STDMETHOD(Enumerate) (IEnumString** ppEnum)
  306. { return (Enumerate (ppEnum, &CLSID_MMC)); }
  307. private:
  308. CStringTable* LookupStringTableByCLSID (const CLSID* pclsid) const;
  309. SC ScGenerateIDPool ();
  310. private:
  311. CStringIDPool m_IDPool;
  312. CLSIDToStringTableMap m_TableMap;
  313. static const WCHAR s_pszIDPoolStream[];
  314. static const WCHAR s_pszStringsStream[];
  315. };
  316. class CStringEnumerator : public IEnumString, public CComObjectRoot
  317. {
  318. public:
  319. CStringEnumerator ();
  320. ~CStringEnumerator ();
  321. public:
  322. /*
  323. * ATL COM map
  324. */
  325. BEGIN_COM_MAP (CStringEnumerator)
  326. COM_INTERFACE_ENTRY (IEnumString)
  327. END_COM_MAP ()
  328. /*
  329. * IEnumString methods
  330. */
  331. STDMETHOD(Next) (ULONG celt, LPOLESTR *rgelt, ULONG *pceltFetched);
  332. STDMETHOD(Skip) (ULONG celt);
  333. STDMETHOD(Reset) ();
  334. STDMETHOD(Clone) (IEnumString **ppenum);
  335. static HRESULT CreateInstanceWrapper (
  336. CComObject<CStringEnumerator>** ppEnumObject,
  337. IEnumString** ppEnumIface);
  338. bool Init (const EntryList& entries);
  339. private:
  340. typedef std::vector<std::wstring> StringVector;
  341. StringVector m_Strings;
  342. size_t m_cStrings;
  343. size_t m_nCurrentIndex;
  344. };
  345. IStorage& operator>> (IStorage& stg, CMasterStringTable& mst);
  346. IStorage& operator<< (IStorage& stg, const CMasterStringTable& mst);
  347. IStorage& operator>> (IStorage& stg, CComObject<CMasterStringTable>& mst);
  348. IStorage& operator<< (IStorage& stg, const CComObject<CMasterStringTable>& mst);
  349. IStream& operator>> (IStream& stm, CStringTable& st);
  350. IStream& operator<< (IStream& stm, const CStringTable& st);
  351. IStream& operator>> (IStream& stm, CEntry& entry);
  352. IStream& operator<< (IStream& stm, const CEntry& entry);
  353. template<class T>
  354. IStream& operator>> (IStream& stm, CIdentifierPool<T>& pool);
  355. template<class T>
  356. IStream& operator<< (IStream& stm, const CIdentifierPool<T>& pool);
  357. #include "strtable.inl"
  358. #endif /* STRTABLE_H */