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.

339 lines
7.4 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 2000
  6. //
  7. // File: listfile.cpp
  8. //
  9. //
  10. //--------------------------------------------------------------------------
  11. #include "pch.h"
  12. #pragma hdrstop
  13. #include "listfile.h"
  14. const TCHAR g_szPin[] = TEXT("Pin");
  15. const TCHAR g_szUnpin[] = TEXT("Unpin");
  16. const TCHAR g_szDefault[] = TEXT("Default");
  17. bool
  18. CDblNulStrIter::Next(
  19. LPCTSTR *ppsz
  20. ) const
  21. {
  22. ASSERT(NULL != ppsz);
  23. if (m_pszCurrent && *m_pszCurrent)
  24. {
  25. *ppsz = m_pszCurrent;
  26. while(*m_pszCurrent++)
  27. NULL;
  28. return true;
  29. }
  30. return false;
  31. };
  32. //
  33. // Class used to represent a double-nul terminated list of strings.
  34. // Simplifies counting and enumerating substrings.
  35. //
  36. class CDblNulStr
  37. {
  38. public:
  39. CDblNulStr(LPCTSTR psz)
  40. : m_pszStart(psz) { }
  41. DWORD StringCount(void) const;
  42. CDblNulStrIter GetIter(void) const
  43. { return CDblNulStrIter(m_pszStart); }
  44. private:
  45. LPCTSTR m_pszStart;
  46. };
  47. DWORD
  48. CDblNulStr::StringCount(
  49. void
  50. ) const
  51. {
  52. ASSERT(NULL != m_pszStart);
  53. LPCWSTR psz = m_pszStart;
  54. DWORD n = 0;
  55. while(*psz++)
  56. {
  57. n++;
  58. while(*psz++)
  59. NULL;
  60. }
  61. return n;
  62. }
  63. CListFile::CListFile(
  64. LPCTSTR pszFile
  65. ) : m_pszFilesToPin(NULL),
  66. m_pszFilesToUnpin(NULL),
  67. m_pszFilesDefault(NULL)
  68. {
  69. lstrcpyn(m_szFile, pszFile, ARRAYSIZE(m_szFile));
  70. }
  71. CListFile::~CListFile(
  72. void
  73. )
  74. {
  75. if (NULL != m_pszFilesToPin)
  76. {
  77. LocalFree(m_pszFilesToPin);
  78. }
  79. if (NULL != m_pszFilesToUnpin)
  80. {
  81. LocalFree(m_pszFilesToUnpin);
  82. }
  83. if (NULL != m_pszFilesDefault)
  84. {
  85. LocalFree(m_pszFilesDefault);
  86. }
  87. }
  88. HRESULT
  89. CListFile::GetFilesToPin(
  90. CDblNulStrIter *pIter
  91. )
  92. {
  93. HRESULT hr = S_OK;
  94. if (NULL == m_pszFilesToPin)
  95. {
  96. DWORD dwResult = _ReadPathsToPin(&m_pszFilesToPin);
  97. if (ERROR_SUCCESS != dwResult)
  98. {
  99. hr = HRESULT_FROM_WIN32(dwResult);
  100. }
  101. }
  102. if (SUCCEEDED(hr))
  103. {
  104. *pIter = CDblNulStrIter(m_pszFilesToPin);
  105. }
  106. return hr;
  107. }
  108. HRESULT
  109. CListFile::GetFilesToUnpin(
  110. CDblNulStrIter *pIter
  111. )
  112. {
  113. HRESULT hr = S_OK;
  114. if (NULL == m_pszFilesToUnpin)
  115. {
  116. DWORD dwResult = _ReadPathsToUnpin(&m_pszFilesToUnpin);
  117. if (ERROR_SUCCESS != dwResult)
  118. {
  119. hr = HRESULT_FROM_WIN32(dwResult);
  120. }
  121. }
  122. if (SUCCEEDED(hr))
  123. {
  124. *pIter = CDblNulStrIter(m_pszFilesToUnpin);
  125. }
  126. return hr;
  127. }
  128. HRESULT
  129. CListFile::GetFilesDefault(
  130. CDblNulStrIter *pIter
  131. )
  132. {
  133. HRESULT hr = S_OK;
  134. if (NULL == m_pszFilesDefault)
  135. {
  136. DWORD dwResult = _ReadPathsDefault(&m_pszFilesDefault);
  137. if (ERROR_SUCCESS != dwResult)
  138. {
  139. hr = HRESULT_FROM_WIN32(dwResult);
  140. }
  141. }
  142. if (SUCCEEDED(hr))
  143. {
  144. *pIter = CDblNulStrIter(m_pszFilesDefault);
  145. }
  146. return hr;
  147. }
  148. //
  149. // Load a value string from an INI file. Automatically
  150. // grows buffer to necessary length. Returned string must be freed
  151. // using LocalFree().
  152. //
  153. DWORD
  154. CListFile::_ReadString(
  155. LPCTSTR pszAppName, // May be NULL.
  156. LPCTSTR pszKeyName, // May be NULL.
  157. LPCTSTR pszDefault,
  158. LPTSTR *ppszResult
  159. )
  160. {
  161. ASSERT(NULL != pszDefault);
  162. ASSERT(NULL != ppszResult);
  163. LPTSTR pszValue = NULL;
  164. const DWORD CCHGROW = MAX_PATH;
  165. DWORD cchValue = CCHGROW;
  166. DWORD dwResult = ERROR_SUCCESS;
  167. do
  168. {
  169. pszValue = (LPTSTR)LocalAlloc(LPTR, cchValue * sizeof(*pszValue));
  170. if (NULL == pszValue)
  171. {
  172. dwResult = ERROR_INSUFFICIENT_BUFFER;
  173. }
  174. else
  175. {
  176. DWORD cchCopied = GetPrivateProfileString(pszAppName,
  177. pszKeyName,
  178. pszDefault,
  179. pszValue,
  180. cchValue,
  181. m_szFile);
  182. if (((NULL == pszAppName || NULL == pszKeyName) && (cchValue - 2) == cchCopied) ||
  183. ((NULL != pszAppName && NULL != pszKeyName) && (cchValue - 1) == cchCopied))
  184. {
  185. //
  186. // Buffer too small. Reallocate and try again.
  187. //
  188. cchValue += CCHGROW;
  189. LocalFree(pszValue);
  190. pszValue = NULL;
  191. }
  192. }
  193. }
  194. while(NULL == pszValue && ERROR_SUCCESS == dwResult);
  195. if (ERROR_SUCCESS == dwResult)
  196. {
  197. //
  198. // Don't forget, this data can be a double-nul terminated string.
  199. // Don't try to copy it to an exact-sized buffer using strcpy.
  200. //
  201. ASSERT(NULL != pszValue);
  202. *ppszResult = pszValue;
  203. }
  204. return dwResult;
  205. }
  206. //
  207. // Read all of the item names in a given INI file section.
  208. // The names are returned in a double-nul term string.
  209. // Caller must free returned string using LocalFree.
  210. // *pbEmpty is set to true if no items were found.
  211. //
  212. DWORD
  213. CListFile::_ReadSectionItemNames(
  214. LPCTSTR pszSection,
  215. LPTSTR *ppszItemNames,
  216. bool *pbEmpty // [optional] Default == NULL.
  217. )
  218. {
  219. bool bEmpty = false;
  220. LPTSTR pszItemNames;
  221. DWORD dwResult = _ReadString(pszSection, NULL, TEXT(""), &pszItemNames);
  222. if (ERROR_SUCCESS == dwResult && TEXT('\0') == *pszItemNames)
  223. {
  224. LocalFree(pszItemNames);
  225. bEmpty = true;
  226. }
  227. else
  228. {
  229. *ppszItemNames = pszItemNames;
  230. }
  231. if (NULL != pbEmpty)
  232. {
  233. *pbEmpty = bEmpty;
  234. }
  235. return dwResult;
  236. }
  237. //
  238. // Read a single item value from an INI file.
  239. // Caller must free returned string using LocalFree.
  240. //
  241. DWORD
  242. CListFile::_ReadItemValue(
  243. LPCTSTR pszSection,
  244. LPCTSTR pszItemName,
  245. LPTSTR *ppszItemValue
  246. )
  247. {
  248. LPTSTR pszValue;
  249. DWORD dwResult = _ReadString(pszSection, pszItemName, TEXT(""), &pszValue);
  250. if (ERROR_SUCCESS == dwResult && TEXT('\0') == *pszValue)
  251. {
  252. LocalFree(pszValue);
  253. dwResult = ERROR_INVALID_DATA;
  254. }
  255. else
  256. {
  257. *ppszItemValue = pszValue;
  258. }
  259. return dwResult;
  260. }
  261. //
  262. // Read the names of all paths in the [Pin] section.
  263. // Caller must free returned string using LocalFree
  264. //
  265. DWORD
  266. CListFile::_ReadPathsToPin(
  267. LPTSTR *ppszNames,
  268. bool *pbEmpty
  269. )
  270. {
  271. return _ReadSectionItemNames(g_szPin, ppszNames, pbEmpty);
  272. }
  273. //
  274. // Read the names of all paths in the [Unpin] section.
  275. // Caller must free returned string using LocalFree
  276. //
  277. DWORD
  278. CListFile::_ReadPathsToUnpin(
  279. LPWSTR *ppszNames,
  280. bool *pbEmpty
  281. )
  282. {
  283. return _ReadSectionItemNames(g_szUnpin, ppszNames, pbEmpty);
  284. }
  285. //
  286. // Read the names of all paths in the [Default] section.
  287. // Caller must free returned string using LocalFree
  288. //
  289. DWORD
  290. CListFile::_ReadPathsDefault(
  291. LPWSTR *ppszNames,
  292. bool *pbEmpty
  293. )
  294. {
  295. return _ReadSectionItemNames(g_szDefault, ppszNames, pbEmpty);
  296. }