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.

526 lines
19 KiB

  1. /*--------------------------------------------------------------------------------------------------------
  2. * Copyright (c) 1998 Microsoft Corporation
  3. *
  4. * Module Name:
  5. *
  6. * Registry.cpp
  7. *
  8. * Abstract:
  9. *
  10. * Registry.cpp: implementation of the CRegistry class.
  11. * This class helps with registry by allocating memory by itself
  12. * As a result caller must copy the pointer returned by Get functions
  13. * immediately.
  14. *
  15. *
  16. *
  17. * Author:
  18. *
  19. * Makarand Patwardhan - April 9, 1997
  20. *
  21. * -------------------------------------------------------------------------------------------------------*/
  22. #include "stdafx.h"
  23. #include "Registry.h"
  24. /*--------------------------------------------------------------------------------------------------------
  25. * Constructor
  26. * -------------------------------------------------------------------------------------------------------*/
  27. CRegistry::CRegistry()
  28. {
  29. m_pMemBlock = NULL;
  30. m_hKey = NULL;
  31. m_iEnumIndex = -1;
  32. m_iEnumValueIndex = -1;
  33. #ifdef DBG
  34. m_dwSizeDebugOnly = 0;
  35. #endif
  36. }
  37. /*--------------------------------------------------------------------------------------------------------
  38. * Destructor
  39. * -------------------------------------------------------------------------------------------------------*/
  40. CRegistry::~CRegistry()
  41. {
  42. if (m_hKey != NULL)
  43. {
  44. RegCloseKey(m_hKey);
  45. m_hKey = NULL;
  46. }
  47. Release();
  48. }
  49. /*--------------------------------------------------------------------------------------------------------
  50. * void Allocate (DWORD dwSize)
  51. * This private function is used for allocating the memory for
  52. * reading registry
  53. * returns the pointer to memory allocated.
  54. * -------------------------------------------------------------------------------------------------------*/
  55. void *CRegistry::Allocate (DWORD dwSize)
  56. {
  57. ASSERT(dwSize != 0);
  58. if (m_pMemBlock)
  59. Release();
  60. m_pMemBlock = new BYTE[dwSize];
  61. #ifdef DBG
  62. // remember the size of the block to be allocated.
  63. m_dwSizeDebugOnly = dwSize;
  64. #endif
  65. return m_pMemBlock;
  66. }
  67. /*--------------------------------------------------------------------------------------------------------
  68. * void Release ()
  69. * This private function is used for releasing internal memory block
  70. * -------------------------------------------------------------------------------------------------------*/
  71. void CRegistry::Release ()
  72. {
  73. if (m_pMemBlock)
  74. {
  75. #ifdef DBG
  76. // fistly fill up the block we allocated previously with garbage.
  77. // so that if anybody is using this block, it is more lilely to
  78. // catch the bug.
  79. ASSERT(m_dwSizeDebugOnly != 0);
  80. FillMemory(m_pMemBlock, m_dwSizeDebugOnly, 'c');
  81. m_dwSizeDebugOnly = 0;
  82. #endif
  83. delete [] m_pMemBlock;
  84. }
  85. m_pMemBlock = 0;
  86. }
  87. /*--------------------------------------------------------------------------------------------------------
  88. * DWORD CRegistry::CreateKey(HKEY hKey, LPCTSTR lpSubKey, REGSAM access = KEY_ALL_ACCESS, DWORD *pDisposition = NULL)
  89. * opens/creates the key specified. before attempting any operation on any key/value. this function
  90. * must be called.
  91. * hKey - hive
  92. * lpSubKey - Path of the key in the format _T("SYSTEM\\CurrentControlSet\\Control\\Terminal Server")
  93. * access - access desired. like REG_READ, REG_WRITE..
  94. * RETURNS error code.
  95. * -------------------------------------------------------------------------------------------------------*/
  96. DWORD CRegistry::CreateKey(HKEY hKey, LPCTSTR lpSubKey, REGSAM access /*= KEY_ALL_ACCESS*/, DWORD *pDisposition /*= NULL*/)
  97. {
  98. ASSERT(lpSubKey);
  99. ASSERT(*lpSubKey != '\\');
  100. if (m_hKey != NULL)
  101. {
  102. RegCloseKey(m_hKey);
  103. m_hKey = NULL;
  104. }
  105. DWORD dwDisposition;
  106. LONG lResult = RegCreateKeyEx(
  107. hKey, // handle of an open key
  108. lpSubKey, // address of subkey name
  109. 0, // reserved
  110. NULL, // address of class string
  111. REG_OPTION_NON_VOLATILE , // special options flag
  112. access, // desired security access
  113. NULL, // address of key security structure
  114. &m_hKey, // address of buffer for opened handle
  115. &dwDisposition // address of disposition value buffer
  116. );
  117. if (lResult != ERROR_SUCCESS)
  118. {
  119. m_hKey = NULL;
  120. }
  121. if (pDisposition)
  122. *pDisposition = dwDisposition;
  123. return lResult;
  124. }
  125. /*--------------------------------------------------------------------------------------------------------
  126. * DWORD OpenKey(HKEY hKey, LPCTSTR lpSubKey, REGSAM access) ()
  127. * opens the key specified. before attempting any operation on any key/value. this function
  128. * must be called.
  129. * hKey - hive
  130. * lpSubKey - Path of the key in the format _T("SYSTEM\\CurrentControlSet\\Control\\Terminal Server")
  131. * access - access desired. like REG_READ, REG_WRITE..
  132. * RETURNS error code.
  133. * -------------------------------------------------------------------------------------------------------*/
  134. DWORD CRegistry::OpenKey(HKEY hKey, LPCTSTR lpSubKey, REGSAM access /*= KEY_ALL_ACCESS*/ )
  135. {
  136. ASSERT(lpSubKey);
  137. ASSERT(*lpSubKey != '\\');
  138. if (m_hKey != NULL)
  139. {
  140. RegCloseKey(m_hKey);
  141. m_hKey = NULL;
  142. }
  143. LONG lResult = RegOpenKeyEx(
  144. hKey, // handle of open key
  145. lpSubKey, // address of name of subkey to open
  146. 0 , // reserved
  147. access, // security access mask
  148. &m_hKey // address of handle of open key
  149. );
  150. if (lResult != ERROR_SUCCESS)
  151. {
  152. m_hKey = NULL;
  153. }
  154. return lResult;
  155. }
  156. DWORD CRegistry::RecurseDeleteKey (LPCTSTR lpSubKey)
  157. {
  158. ASSERT(lpSubKey);
  159. ASSERT(m_hKey);
  160. CRegistry reg;
  161. DWORD dwError = reg.OpenKey(m_hKey, lpSubKey);
  162. if (dwError != ERROR_SUCCESS)
  163. return dwError;
  164. LPTSTR lpChildKey;
  165. DWORD dwSize;
  166. // we needn't/shouldn't use GetNextSubKey in here
  167. // as we are deleting the keys in the loop.
  168. while (ERROR_SUCCESS == reg.GetFirstSubKey(&lpChildKey, &dwSize))
  169. {
  170. reg.RecurseDeleteKey(lpChildKey);
  171. }
  172. return RegDeleteKey(m_hKey, lpSubKey);
  173. }
  174. /*--------------------------------------------------------------------------------------------------------
  175. * DWORD ReadReg(LPCTSTR lpValue, LPBYTE *lppbyte, DWORD *pdw, DWORD dwDatatype)
  176. * Reads the registry used internally.
  177. * LPCTSTR lpValue - value to be read.
  178. * LPBYTE *lppbyte - address of the lpbyte at which to place the output buffer.
  179. * DWORD *pdw - address of dword in which size of the buffer (in bytes) is returned.
  180. * dword datatype - datatype you are expecting.
  181. * RETURNS error code.
  182. * -------------------------------------------------------------------------------------------------------*/
  183. DWORD CRegistry::ReadReg(LPCTSTR lpValue, LPBYTE *lppbyte, DWORD *pdw, DWORD dwDatatype)
  184. {
  185. ASSERT(lpValue);
  186. ASSERT(lppbyte);
  187. ASSERT(pdw);
  188. ASSERT(m_hKey != NULL);
  189. *pdw = 0;
  190. DWORD dwType;
  191. DWORD lResult = RegQueryValueEx(
  192. m_hKey, // handle of key to query
  193. lpValue, // address of name of value to query
  194. 0, // reserved
  195. &dwType, // address of buffer for value type
  196. 0, // address of data buffer
  197. pdw // address of data buffer size
  198. );
  199. if (lResult == ERROR_SUCCESS)
  200. {
  201. ASSERT(dwType == dwDatatype || dwType == REG_EXPAND_SZ);
  202. if (0 == Allocate(*pdw))
  203. return ERROR_OUTOFMEMORY;
  204. lResult = RegQueryValueEx(
  205. m_hKey, // handle of key to query
  206. lpValue, // address of name of value to query
  207. 0, // reserved
  208. &dwType, // address of buffer for value type
  209. m_pMemBlock, // address of data buffer
  210. pdw // address of data buffer size
  211. );
  212. ASSERT (ERROR_MORE_DATA != lResult);
  213. if (lResult == ERROR_SUCCESS)
  214. *lppbyte = m_pMemBlock;
  215. }
  216. return lResult;
  217. }
  218. /*--------------------------------------------------------------------------------------------------------
  219. * DWORD ReadRegString(LPCTSTR lpValue, LPTSTR *lppStr, DWORD *pdw)
  220. * Reads A string (REG_SZ) from the registry
  221. * LPCTSTR lpValue value to be read.
  222. * LPTSTR *lppStr - address of LPTSTR in which resultant buffer is returned. caller must copy
  223. * the buffer to immediately. caller must not use this buffer except for copying it.
  224. * caller must not write to this buffer.
  225. * DWORD *pdw - address of dword in which size of the buffer (in bytes) is returned.
  226. * RETURNS error code.
  227. * -------------------------------------------------------------------------------------------------------*/
  228. DWORD CRegistry::ReadRegString(LPCTSTR lpValue, LPTSTR *lppStr, DWORD *pdw)
  229. {
  230. return ReadReg(lpValue, (LPBYTE *)lppStr, pdw, REG_SZ);
  231. }
  232. /*--------------------------------------------------------------------------------------------------------
  233. * DWORD ReadRegDWord(LPCTSTR lpValue, DWORD *pdw)
  234. * Reads A string (REG_SZ) from the registry
  235. * LPCTSTR lpValue value to be read.
  236. * DWORD *pdw - address of dword in which the read dword returned.
  237. * RETURNS error code.
  238. * -------------------------------------------------------------------------------------------------------*/
  239. DWORD CRegistry::ReadRegDWord(LPCTSTR lpValue, DWORD *pdw)
  240. {
  241. ASSERT(pdw);
  242. DWORD dwSize;
  243. LPBYTE pByte;
  244. DWORD dwReturn = ReadReg(lpValue, &pByte, &dwSize, REG_DWORD);
  245. ASSERT(dwSize == sizeof(DWORD));
  246. *pdw = * LPDWORD(pByte);
  247. return dwReturn;
  248. }
  249. /*--------------------------------------------------------------------------------------------------------
  250. * DWORD ReadRegMultiString(LPCTSTR lpValue, LPTSTR *lppStr, DWORD *pdw)
  251. * Reads A string (REG_MULTI_SZ) from the registry
  252. * LPCTSTR lpValue value to be read.
  253. * LPTSTR *lppStr - address of LPTSTR in which resultant buffer is returned. caller must copy
  254. * the buffer to immediately. caller must not use this buffer except for copying it.
  255. * caller must not write to this buffer.
  256. * DWORD *pdw - address of dword in which size of the buffer (in bytes) is returned.
  257. * RETURNS error code.
  258. * -------------------------------------------------------------------------------------------------------*/
  259. DWORD CRegistry::ReadRegMultiString(LPCTSTR lpValue, LPTSTR *lppStr, DWORD *pdw)
  260. {
  261. return ReadReg(lpValue, (LPBYTE *)lppStr, pdw, REG_MULTI_SZ);
  262. }
  263. /*--------------------------------------------------------------------------------------------------------
  264. * DWORD ReadRegBinary(LPCTSTR lpValue, LPBYTE *lppByte, DWORD *pdw)
  265. * Reads A string (REG_MULTI_SZ) from the registry
  266. * LPCTSTR lpValue value to be read.
  267. * LPBYTE *lppByte - address of LPBYTE in which resultant buffer is returned. caller must copy
  268. * the buffer to immediately. caller must not use this buffer except for copying it.
  269. * caller must not write to this buffer.
  270. * DWORD *pdw - address of dword in which size of the buffer (in bytes) is returned.
  271. * RETURNS error code.
  272. * -------------------------------------------------------------------------------------------------------*/
  273. DWORD CRegistry::ReadRegBinary(LPCTSTR lpValue, LPBYTE *lppByte, DWORD *pdw)
  274. {
  275. return ReadReg(lpValue, lppByte, pdw, REG_BINARY);
  276. }
  277. /*--------------------------------------------------------------------------------------------------------
  278. * DWORD GetFirstSubKey(LPTSTR *lppStr, DWORD *pdw)
  279. * Reads a first subkey for the key
  280. * LPTSTR *lppStr - address of LPTSTR in which resultant buffer is returned. caller must copy
  281. * the buffer to immediately. caller must not use this buffer except for copying it.
  282. * caller must not write to this buffer.
  283. * used to enumerate the registry.
  284. * DWORD *pdw - address of dword in which size of the buffer (in bytes) is returned.
  285. * RETURNS error code.
  286. * -------------------------------------------------------------------------------------------------------*/
  287. DWORD CRegistry::GetFirstSubKey(LPTSTR *lppStr, DWORD *pdw)
  288. {
  289. ASSERT(lppStr);
  290. ASSERT(pdw);
  291. m_iEnumIndex = 0;
  292. return GetNextSubKey(lppStr, pdw);
  293. }
  294. /*--------------------------------------------------------------------------------------------------------
  295. * DWORD GetNextSubKey(LPTSTR *lppStr, DWORD *pdw
  296. * Reads the next subkey for the key
  297. * LPTSTR *lppStr - address of LPTSTR in which resultant buffer is returned. caller must copy
  298. * the buffer to immediately. caller must not use this buffer except for copying it.
  299. * caller must not write to this buffer.
  300. * used to enumerate the registry.
  301. * DWORD *pdw - address of dword in which size of the buffer (in bytes) is returned.
  302. * RETURNS error code.
  303. * -------------------------------------------------------------------------------------------------------*/
  304. DWORD CRegistry::GetNextSubKey(LPTSTR *lppStr, DWORD *pdw)
  305. {
  306. ASSERT(lppStr);
  307. ASSERT(pdw);
  308. ASSERT(m_hKey != NULL);
  309. ASSERT(m_iEnumIndex >= 0); // must call GetFirstSubKey first.
  310. //FILETIME unused;
  311. *pdw = 256;
  312. if (0 == Allocate(*pdw))
  313. return ERROR_NOT_ENOUGH_MEMORY;
  314. LONG lResult = RegEnumKeyEx(
  315. m_hKey, // handle of key to enumerate
  316. m_iEnumIndex, // index of subkey to enumerate
  317. (LPTSTR)m_pMemBlock, // address of buffer for subkey name
  318. pdw, // address for size of subkey buffer
  319. 0, // reserved
  320. NULL, // address of buffer for class string
  321. NULL, // address for size of class buffer
  322. NULL // address for time key last written to
  323. );
  324. (*pdw)++; // since null is not included in the size.
  325. if (ERROR_NO_MORE_ITEMS == lResult)
  326. return lResult;
  327. m_iEnumIndex++;
  328. if (lResult == ERROR_SUCCESS)
  329. *lppStr = (LPTSTR)m_pMemBlock;
  330. return lResult;
  331. }
  332. /*--------------------------------------------------------------------------------------------------------
  333. * DWORD GetFirstValue(LPTSTR *lppStr, DWORD *pdw, DWORD *pDataType)
  334. * Reads a first value for the key
  335. * LPTSTR *lppStr - address of LPTSTR in which resultant buffer is returned. caller must copy
  336. * the buffer to immediately. caller must not use this buffer except for copying it.
  337. * caller must not write to this buffer.
  338. * used to enumerate the registry.
  339. * DWORD *pdw - address of dword in which size of the buffer (in bytes) is returned.
  340. * DWORD *pDataType - datatype of the value is returned in this one.
  341. * RETURNS error code.
  342. * -------------------------------------------------------------------------------------------------------*/
  343. DWORD CRegistry::GetFirstValue(LPTSTR *lppStr, DWORD *pdw, DWORD *pDataType)
  344. {
  345. ASSERT(lppStr);
  346. ASSERT(pdw);
  347. ASSERT(pDataType);
  348. m_iEnumValueIndex = 0;
  349. return GetNextValue(lppStr, pdw, pDataType);
  350. }
  351. /*--------------------------------------------------------------------------------------------------------
  352. * DWORD GetNextValue(LPTSTR *lppStr, DWORD *pdw, DWORD *pDataType)
  353. * Reads a next value for the key
  354. * LPTSTR *lppStr - address of LPTSTR in which resultant buffer is returned. caller must copy
  355. * the buffer to immediately. caller must not use this buffer except for copying it.
  356. * caller must not write to this buffer.
  357. * used to enumerate the registry.
  358. * DWORD *pdw - address of dword in which size of the buffer (in bytes) is returned.
  359. * DWORD *pDataType - datatype of the value is returned in this one.
  360. * RETURNS error code.
  361. * -------------------------------------------------------------------------------------------------------*/
  362. DWORD CRegistry::GetNextValue(LPTSTR *lppStr, DWORD *pdw, DWORD *pDataType)
  363. {
  364. ASSERT(lppStr);
  365. ASSERT(pdw);
  366. ASSERT(pDataType);
  367. ASSERT(m_hKey != NULL);
  368. ASSERT(m_iEnumValueIndex >= 0); // must call GetFirstSubKey first.
  369. *pdw = 256;
  370. if (0 == Allocate(*pdw))
  371. return ERROR_NOT_ENOUGH_MEMORY;
  372. LONG lResult = RegEnumValue(
  373. m_hKey, // handle of key to query
  374. m_iEnumValueIndex, // index of value to query
  375. (LPTSTR)m_pMemBlock, // address of buffer for value string
  376. pdw, // address for size of value buffer
  377. 0, // reserved
  378. pDataType, // address of buffer for type code
  379. NULL, // address of buffer for value data maks_todo : use this
  380. NULL // address for size of data buffer
  381. );
  382. (*pdw)++; // since null is not included in the size.
  383. if (ERROR_NO_MORE_ITEMS == lResult)
  384. return lResult;
  385. m_iEnumValueIndex++;
  386. if (lResult == ERROR_SUCCESS)
  387. *lppStr = (LPTSTR)m_pMemBlock;
  388. return lResult;
  389. }
  390. /*--------------------------------------------------------------------------------------------------------
  391. * DWORD WriteRegString(LPCTSTR lpValueName, LPCTSTR lpStr)
  392. * writes REG_SZ value into the registry
  393. * LPCTSTR lpValueName - value name to be written to
  394. * LPCTSTR lpStr - data to be written
  395. * RETURNS error code.
  396. * -------------------------------------------------------------------------------------------------------*/
  397. DWORD CRegistry::WriteRegString(LPCTSTR lpValueName, LPCTSTR lpStr)
  398. {
  399. ASSERT(m_hKey != NULL); // call setkey before calling this function.
  400. ASSERT(lpValueName);
  401. ASSERT(lpStr);
  402. DWORD dwSize = (_tcslen(lpStr) + 1) * sizeof(TCHAR) / sizeof(BYTE);
  403. return RegSetValueEx(
  404. m_hKey, // handle of key to set value for
  405. lpValueName, // address of value to set
  406. 0, // Reserved
  407. REG_SZ, // flag for value type
  408. (LPBYTE)lpStr, // address of value data
  409. dwSize // size of value data
  410. );
  411. }
  412. /*--------------------------------------------------------------------------------------------------------
  413. * DWORD WriteRegMultiString(LPCTSTR lpValueName, LPCTSTR lpStr, DWORD dwSize)
  414. * writes REG_MULTI_SZ value into the registry
  415. * LPCTSTR lpValueName - value name to be written to
  416. * LPCTSTR lpStr - data to be written
  417. * DWORD dwSize - size of data.
  418. * RETURNS error code.
  419. * -------------------------------------------------------------------------------------------------------*/
  420. DWORD CRegistry::WriteRegMultiString(LPCTSTR lpValueName, LPCTSTR lpStr, DWORD dwSize)
  421. {
  422. ASSERT(m_hKey != NULL); // call setkey before calling this function.
  423. ASSERT(lpValueName);
  424. ASSERT(lpStr);
  425. #ifdef DBG
  426. // lets make sure that the given size is right.
  427. LPCTSTR lpTemp = lpStr;
  428. DWORD rightsize = 0;
  429. while (_tcslen(lpTemp) > 0)
  430. {
  431. rightsize += _tcslen(lpTemp) + 1;
  432. lpTemp += _tcslen(lpTemp) + 1;
  433. }
  434. ASSERT(*lpTemp == 0); // final NULL.
  435. rightsize++; // account for final terminating null
  436. rightsize *= sizeof(TCHAR) / sizeof(BYTE); // size must be in bytes.
  437. ASSERT(dwSize == rightsize);
  438. #endif
  439. return RegSetValueEx(
  440. m_hKey, // handle of key to set value for
  441. lpValueName, // address of value to set
  442. 0, // Reserved
  443. REG_MULTI_SZ, // flag for value type
  444. (LPBYTE)lpStr, // address of value data
  445. dwSize // size of value data
  446. );
  447. }
  448. // EOF