Leaked source code of windows server 2003
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.

436 lines
13 KiB

  1. #ifndef _INC_DBLNUL_H
  2. #define _INC_DBLNUL_H
  3. #include <windows.h>
  4. #include <strsafe.h>
  5. #ifndef ASSERT
  6. # include <assert.h>
  7. # define ASSERT assert
  8. #endif
  9. #ifdef __cplusplus
  10. //
  11. //-----------------------------------------------------------------------------
  12. // CDblNulTermListStrLib
  13. //-----------------------------------------------------------------------------
  14. //
  15. // Type-specific string functions so the compiler can select the correct version
  16. // to match the list type.
  17. //
  18. class CDblNulTermListStrLib
  19. {
  20. public:
  21. static int StringLength(LPCSTR pszA)
  22. { return lstrlenA(pszA); }
  23. static int StringLength(LPCWSTR pszW)
  24. { return lstrlenW(pszW); }
  25. static HRESULT StringCopy(LPSTR pszDestA, size_t cchDestA, LPCSTR pszSrcA)
  26. { return StringCchCopyA(pszDestA, cchDestA, pszSrcA); }
  27. static HRESULT StringCopy(LPWSTR pszDestW, size_t cchDestW, LPCWSTR pszSrcW)
  28. { return StringCchCopyW(pszDestW, cchDestW, pszSrcW); }
  29. };
  30. //
  31. //-----------------------------------------------------------------------------
  32. // CDblNulTermListEnumImpl<T>
  33. //-----------------------------------------------------------------------------
  34. //
  35. // For iterating over items in a double-nul terminated list of
  36. // text strings. An enumerator may be generated from an existing
  37. // dblnul list object or may be created for a raw double nul terminated string.
  38. //
  39. template <typename T>
  40. class CDblNulTermListEnumImpl
  41. {
  42. public:
  43. explicit CDblNulTermListEnumImpl(const T *pszList)
  44. : m_pszList(pszList),
  45. m_pszCurrent(pszList) { }
  46. ~CDblNulTermListEnumImpl(void) { }
  47. //
  48. // Retrieve address of next string in list.
  49. //
  50. HRESULT Next(const T **ppszItem);
  51. //
  52. // Reset enumerator to the start of the list.
  53. //
  54. void Reset(void)
  55. { m_pszCurrent = m_pszList; }
  56. private:
  57. const T *m_pszList;
  58. const T *m_pszCurrent;
  59. };
  60. // ----------------------------------------------------------------------------
  61. // CEmptyList
  62. // ----------------------------------------------------------------------------
  63. //
  64. // Provides type-sensitive empty dbl-nul-term lists.
  65. // This is so that an empty dbl-nul-term list object will still provide a valid
  66. // dbl-nul-term list if no items are added.
  67. //
  68. class CEmptyList
  69. {
  70. public:
  71. CEmptyList(void)
  72. {
  73. m_pszEmptyA = "\0";
  74. m_pszEmptyW = L"\0";
  75. }
  76. operator LPCSTR() const
  77. { return m_pszEmptyA; }
  78. operator LPCWSTR() const
  79. { return m_pszEmptyW; }
  80. bool operator == (LPCSTR pszA) const
  81. { return m_pszEmptyA == pszA; }
  82. bool operator == (LPCWSTR pszW) const
  83. { return m_pszEmptyW == pszW; }
  84. bool operator != (LPCSTR pszA) const
  85. { return !operator == (pszA); }
  86. bool operator != (LPCWSTR pszW) const
  87. { return !operator == (pszW); }
  88. private:
  89. LPCSTR m_pszEmptyA;
  90. LPCWSTR m_pszEmptyW;
  91. };
  92. //
  93. //-----------------------------------------------------------------------------
  94. // CDblNulTermListImpl<T>
  95. //-----------------------------------------------------------------------------
  96. //
  97. template <typename T>
  98. class CDblNulTermListImpl
  99. {
  100. public:
  101. explicit CDblNulTermListImpl(int cchGrowMin = MAX_PATH)
  102. : m_psz((T *) ((const T *)s_Empty)),
  103. m_cchAlloc(0),
  104. m_cchUsed(0),
  105. m_cElements(0),
  106. m_cchGrowMin(cchGrowMin) { }
  107. ~CDblNulTermListImpl(void)
  108. { if (s_Empty != m_psz) LocalFree(m_psz); }
  109. //
  110. // Add a string to the list.
  111. //
  112. HRESULT Add(const T *psz);
  113. //
  114. // Clear the list of all content.
  115. //
  116. void Clear(void);
  117. //
  118. // Return the count of strings in the list.
  119. //
  120. int Count(void) const
  121. { return m_cElements; }
  122. //
  123. // Return the number of bytes used by the list.
  124. // +1 for the list's terminating nul.
  125. //
  126. int SizeBytes(void) const
  127. { return (m_cchUsed + 1) * sizeof(T); }
  128. //
  129. // Retrieve the address of the start of the list buffer.
  130. // Use this and SizeBytes() to copy the list buffer.
  131. //
  132. // CopyMemory(pbDest, (LPCTSTR)list, list.SizeBytes());
  133. //
  134. operator const T * () const
  135. { return m_psz; }
  136. //
  137. // Create an enumerator for enumerating strings in the list.
  138. //
  139. CDblNulTermListEnumImpl<T> CreateEnumerator(void) const
  140. { return CDblNulTermListEnumImpl<T>(m_psz); }
  141. private:
  142. T * m_psz; // The text buffer.
  143. int m_cchAlloc; // Total allocation in chars.
  144. int m_cchUsed; // Total used excluding FINAL nul term.
  145. int m_cElements; // Count of strings in list.
  146. const int m_cchGrowMin; // Minimum chars to grow each expansion.
  147. static CEmptyList s_Empty;
  148. HRESULT _Grow(int cchGrowMin);
  149. //
  150. // Prevent copy.
  151. //
  152. CDblNulTermListImpl(const CDblNulTermListImpl& rhs);
  153. CDblNulTermListImpl& operator = (const CDblNulTermListImpl& rhs);
  154. };
  155. //
  156. // The list impl initially points to this so that an uninitialized
  157. // list instance will simply provide an empty list.
  158. //
  159. template <typename T>
  160. CEmptyList CDblNulTermListImpl<T>::s_Empty;
  161. //
  162. // Add a string to a dbl-nul-term list.
  163. //
  164. template <typename T>
  165. HRESULT
  166. CDblNulTermListImpl<T>::Add(
  167. const T *psz
  168. )
  169. {
  170. HRESULT hr = E_FAIL;
  171. //
  172. // +2 for this string's nul and for list nul terminator.
  173. //
  174. const int cchString = CDblNulTermListStrLib::StringLength(psz);
  175. const int cchRequired = cchString + 2;
  176. if ((m_cchAlloc - m_cchUsed) < cchRequired)
  177. {
  178. //
  179. // Grow by the amount required PLUS the "min growth" amount.
  180. // This way a client can choose between one of the two
  181. // following strategies:
  182. //
  183. // 1. low-waste/frequent allocation
  184. // 2. high-waste/infrequent allocation.
  185. //
  186. // The "waste" comes from the unused memory at the end
  187. // of the list after all strings have been added.
  188. //
  189. hr = _Grow(cchRequired + m_cchGrowMin);
  190. if (FAILED(hr))
  191. {
  192. return hr;
  193. }
  194. }
  195. ASSERT(NULL != m_psz);
  196. CDblNulTermListStrLib::StringCopy(m_psz + m_cchUsed, m_cchAlloc - m_cchUsed, psz);
  197. m_cchUsed += cchString + 1;
  198. m_cElements++;
  199. return S_OK;
  200. }
  201. //
  202. // Internal function used for allocating the list buffer as needed.
  203. //
  204. template <typename T>
  205. HRESULT
  206. CDblNulTermListImpl<T>::_Grow(int cchGrow)
  207. {
  208. ASSERT(m_cchGrowMin > 0);
  209. HRESULT hr = E_OUTOFMEMORY;
  210. int cb = (m_cchAlloc + cchGrow) * sizeof(T);
  211. T *p = (T *)LocalAlloc(LPTR, cb);
  212. if (NULL != p)
  213. {
  214. if (s_Empty != m_psz)
  215. {
  216. CopyMemory(p, m_psz, m_cchUsed * sizeof(T));
  217. LocalFree(m_psz);
  218. }
  219. m_psz = p;
  220. m_cchAlloc += cchGrow;
  221. hr = S_OK;
  222. }
  223. return hr;
  224. }
  225. //
  226. // Clears all items from the list.
  227. //
  228. template <typename T>
  229. void
  230. CDblNulTermListImpl<T>::Clear(void)
  231. {
  232. if (s_Empty != m_psz)
  233. {
  234. LocalFree(m_psz);
  235. }
  236. m_psz = (T *) ((const T *)s_Empty);
  237. m_cchAlloc = 0;
  238. m_cchUsed = 0;
  239. m_cElements = 0;
  240. }
  241. //
  242. // Retrieve the address of the next string in the enumeration.
  243. // Returns S_FALSE if enumerator is exhausted.
  244. //
  245. template <typename T>
  246. HRESULT
  247. CDblNulTermListEnumImpl<T>::Next(
  248. const T **ppszItem
  249. )
  250. {
  251. if (*m_pszCurrent)
  252. {
  253. *ppszItem = m_pszCurrent;
  254. m_pszCurrent += CDblNulTermListStrLib::StringLength(m_pszCurrent) + 1;
  255. return S_OK;
  256. }
  257. return S_FALSE;
  258. }
  259. //
  260. // Create some types so clients don't need to deal with templates.
  261. // Clients work with these types:
  262. //
  263. // CDblNulTermList, CDblNulTermListA, CDblNulTermListW
  264. //
  265. // CDblNulTermListEnum, CDblNulTermListEnumA, CDblNulTermListEnumW
  266. //
  267. //
  268. typedef CDblNulTermListImpl<WCHAR> CDblNulTermListW;
  269. typedef CDblNulTermListImpl<char> CDblNulTermListA;
  270. typedef CDblNulTermListEnumImpl<WCHAR> CDblNulTermListEnumW;
  271. typedef CDblNulTermListEnumImpl<char> CDblNulTermListEnumA;
  272. #ifdef UNICODE
  273. # define CDblNulTermList CDblNulTermListW
  274. # define CDblNulTermListEnum CDblNulTermListEnumW
  275. #else
  276. # define CDblNulTermList CDblNulTermListA
  277. # define CDblNulTermListEnum CDblNulTermListEnumA
  278. #endif
  279. #endif // __cplusplus
  280. #ifdef __cplusplus
  281. extern "C" {
  282. #endif
  283. //
  284. // These types and functions support 'C' code or 'C++' code
  285. // that prefers to work with handles rather than classes.
  286. //
  287. typedef void * HDBLNULTERMLISTW;
  288. typedef void * HDBLNULTERMLISTENUMW;
  289. typedef void * HDBLNULTERMLISTA;
  290. typedef void * HDBLNULTERMLISTENUMA;
  291. //
  292. // Create a new dbl-nul-term list.
  293. //
  294. HRESULT DblNulTermListW_Create(int cchGrowMin, HDBLNULTERMLISTW *phList);
  295. HRESULT DblNulTermListA_Create(int cchGrowMin, HDBLNULTERMLISTA *phList);
  296. //
  297. // Destroy a dbl-nul-term list.
  298. //
  299. void DblNulTermListW_Destroy(HDBLNULTERMLISTW hList);
  300. void DblNulTermListA_Destroy(HDBLNULTERMLISTA hList);
  301. //
  302. // Add a string to a dbl-nul-term list.
  303. //
  304. HRESULT DblNulTermListW_Add(HDBLNULTERMLISTW hList, LPCWSTR pszW);
  305. HRESULT DblNulTermListA_Add(HDBLNULTERMLISTA hList, LPCSTR pszA);
  306. //
  307. // Clear all entries in a dbl-nul-term list.
  308. //
  309. void DblNulTermListW_Clear(HDBLNULTERMLISTW hList);
  310. void DblNulTermListA_Clear(HDBLNULTERMLISTA hList);
  311. //
  312. // Return count of entries in a dbl-nul-term list.
  313. //
  314. int DblNulTermListW_Count(HDBLNULTERMLISTW hList);
  315. int DblNulTermListA_Count(HDBLNULTERMLISTA hList);
  316. //
  317. // Retrieve the address of the buffer in a dbl-nul-term list.
  318. //
  319. HRESULT DblNulTermListW_Buffer(HDBLNULTERMLISTW hList, LPCWSTR *ppszW);
  320. HRESULT DblNulTermListA_Buffer(HDBLNULTERMLISTA hList, LPCSTR *ppszA);
  321. //
  322. // Create an enumerator for enumerating the strings in a dbl-nul-term list.
  323. // Enumerator is created from an existing dbl-nul-term list object.
  324. //
  325. HRESULT DblNulTermListW_CreateEnum(HDBLNULTERMLISTA hList, HDBLNULTERMLISTENUMW *phEnum);
  326. HRESULT DblNulTermListA_CreateEnum(HDBLNULTERMLISTW hList, HDBLNULTERMLISTENUMA *phEnum);
  327. //
  328. // Create an enumerator given the address of a raw double nul terminated string.
  329. // The resulting enumerator can be used to enumerate the individual strings.
  330. //
  331. HRESULT DblNulTermListEnumW_Create(LPCWSTR pszW, HDBLNULTERMLISTENUMW *phEnum);
  332. HRESULT DblNulTermListEnumA_Create(LPCSTR pszA, HDBLNULTERMLISTENUMA *phEnum);
  333. //
  334. // Destroy a dbl-nul-term list enumerator.
  335. //
  336. void DblNulTermListEnumW_Destroy(HDBLNULTERMLISTW hList);
  337. void DblNulTermListEnumA_Destroy(HDBLNULTERMLISTA hList);
  338. //
  339. // Retrieve the address of the "next" string in a dbl-nul-term list enumerator.
  340. // Returns S_FALSE when enumerator is exhausted.
  341. //
  342. HRESULT DblNulTermListEnumW_Next(HDBLNULTERMLISTW hList, LPCWSTR *ppszW);
  343. HRESULT DblNulTermListEnumA_Next(HDBLNULTERMLISTA hList, LPCSTR *ppszA);
  344. #ifdef UNICODE
  345. # define HDBLNULTERMLIST HDBLNULTERMLISTW
  346. # define HDBLNULTERMLISTENUM HDBLNULTERMLISTENUMW
  347. # define DblNulTermList_Create DblNulTermListW_Create
  348. # define DblNulTermList_Destroy DblNulTermListW_Destroy
  349. # define DblNulTermList_Add DblNulTermListW_Add
  350. # define DblNulTermList_Clear DblNulTermListW_Clear
  351. # define DblNulTermList_Count DblNulTermListW_Count
  352. # define DblNulTermList_Buffer DblNulTermListW_Buffer
  353. # define DblNulTermList_CreateEnum DblNulTermListW_CreateEnum
  354. # define DblNulTermListEnum_Create DblNulTermListEnumW_Create
  355. # define DblNulTermListEnum_Destroy DblNulTermListEnumW_Destroy
  356. # define DblNulTermListEnum_Next DblNulTermListEnumW_Next
  357. #else
  358. # define HDBLNULTERMLIST HDBLNULTERMLISTA
  359. # define HDBLNULTERMLISTENUM HDBLNULTERMLISTENUMA
  360. # define DblNulTermList_Create DblNulTermListA_Create
  361. # define DblNulTermList_Destroy DblNulTermListA_Destroy
  362. # define DblNulTermList_Add DblNulTermListA_Add
  363. # define DblNulTermList_Clear DblNulTermListA_Clear
  364. # define DblNulTermList_Count DblNulTermListA_Count
  365. # define DblNulTermList_Buffer DblNulTermListA_Buffer
  366. # define DblNulTermList_CreateEnum DblNulTermListA_CreateEnum
  367. # define DblNulTermListEnum_Create DblNulTermListEnumA_Create
  368. # define DblNulTermListEnum_Destroy DblNulTermListEnumA_Destroy
  369. # define DblNulTermListEnum_Next DblNulTermListEnumA_Next
  370. #endif
  371. #ifdef __cplusplus
  372. } // extern "C"
  373. #endif
  374. #endif // INC_DBLNUL_H