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.

851 lines
30 KiB

  1. //Copyright (c) 1998 - 1999 Microsoft Corporation
  2. /*--------------------------------------------------------------------------------------------------------
  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. CRegistry::CRegistry(HKEY hKey)
  38. {
  39. m_pMemBlock = NULL;
  40. m_hKey = hKey;
  41. m_iEnumIndex = -1;
  42. m_iEnumValueIndex = -1;
  43. }
  44. /*--------------------------------------------------------------------------------------------------------
  45. * Destructor
  46. * -------------------------------------------------------------------------------------------------------*/
  47. CRegistry::~CRegistry()
  48. {
  49. if (m_hKey != NULL)
  50. {
  51. RegCloseKey(m_hKey);
  52. m_hKey = NULL;
  53. }
  54. Release();
  55. }
  56. /*--------------------------------------------------------------------------------------------------------
  57. * void Allocate (DWORD dwSize)
  58. * This private function is used for allocating the memory for
  59. * reading registry
  60. * returns the pointer to memory allocated.
  61. * -------------------------------------------------------------------------------------------------------*/
  62. void *CRegistry::Allocate (DWORD dwSize)
  63. {
  64. if (m_pMemBlock)
  65. Release();
  66. m_pMemBlock = new BYTE[dwSize];
  67. #ifdef DBG
  68. // remember the size of the block to be allocated.
  69. m_dwSizeDebugOnly = dwSize;
  70. #endif
  71. return m_pMemBlock;
  72. }
  73. /*--------------------------------------------------------------------------------------------------------
  74. * void Release ()
  75. * This private function is used for releasing internal memory block
  76. * -------------------------------------------------------------------------------------------------------*/
  77. void CRegistry::Release ()
  78. {
  79. if (m_pMemBlock)
  80. {
  81. #ifdef DBG
  82. // fistly fill up the block we allocated previously with garbage.
  83. // so that if anybody is using this block, it is more lilely to
  84. // catch the bug.
  85. FillMemory(m_pMemBlock, m_dwSizeDebugOnly, 'c');
  86. m_dwSizeDebugOnly = 0;
  87. #endif
  88. delete [] m_pMemBlock;
  89. }
  90. m_pMemBlock = 0;
  91. }
  92. ///*--------------------------------------------------------------------------------------------------------
  93. //* DWORD CRegistry::CreateKey(HKEY hKey, LPCTSTR lpSubKey, REGSAM access /*= KEY_ALL_ACCESS*/, DWORD *pDisposition /*= NULL*/, LPSECURITY_ATTRIBUTES lpSecAttr /* = NULL */)
  94. //* opens/creates the key specified. before attempting any operation on any key/value. this function
  95. //* must be called.
  96. //* hKey - hive
  97. //* lpSubKey - Path of the key in the format _T("SYSTEM\\CurrentControlSet\\Control\\Terminal Server")
  98. //* access - access desired. like REG_READ, REG_WRITE..
  99. //* RETURNS error code.
  100. //* -------------------------------------------------------------------------------------------------------*/
  101. DWORD CRegistry::CreateKey(HKEY hKey, LPCTSTR lpSubKey, REGSAM access /*= KEY_ALL_ACCESS*/, DWORD *pDisposition /*= NULL*/, LPSECURITY_ATTRIBUTES lpSecAttr /* = NULL */)
  102. {
  103. ASSERT(lpSubKey);
  104. ASSERT(*lpSubKey != '\\');
  105. // security descriptor should be null or it should be a valid one.
  106. ASSERT(!lpSecAttr || IsValidSecurityDescriptor(lpSecAttr->lpSecurityDescriptor));
  107. ASSERT(lpSubKey);
  108. ASSERT(*lpSubKey != '\\');
  109. if (m_hKey != NULL)
  110. {
  111. RegCloseKey(m_hKey);
  112. m_hKey = NULL;
  113. }
  114. DWORD dwDisposition;
  115. LONG lResult = RegCreateKeyEx(
  116. hKey, // handle of an open key
  117. lpSubKey, // address of subkey name
  118. 0, // reserved
  119. NULL, // address of class string
  120. REG_OPTION_NON_VOLATILE , // special options flag
  121. access, // desired security access
  122. lpSecAttr, // address of key security structure
  123. &m_hKey, // address of buffer for opened handle
  124. &dwDisposition // address of disposition value buffer
  125. );
  126. if (lResult != ERROR_SUCCESS)
  127. {
  128. m_hKey = NULL;
  129. }
  130. if (pDisposition)
  131. *pDisposition = dwDisposition;
  132. return lResult;
  133. }
  134. /*--------------------------------------------------------------------------------------------------------
  135. * DWORD OpenKey(HKEY hKey, LPCTSTR lpSubKey, REGSAM access) ()
  136. * opens the key specified. before attempting any operation on any key/value. this function
  137. * must be called.
  138. * hKey - hive
  139. * lpSubKey - Path of the key in the format _T("SYSTEM\\CurrentControlSet\\Control\\Terminal Server")
  140. * access - access desired. like REG_READ, REG_WRITE..
  141. * RETURNS error code.
  142. * -------------------------------------------------------------------------------------------------------*/
  143. DWORD CRegistry::OpenKey(HKEY hKey, LPCTSTR lpSubKey, REGSAM access /*= KEY_ALL_ACCESS*/ )
  144. {
  145. ASSERT(lpSubKey);
  146. ASSERT(*lpSubKey != '\\');
  147. if (m_hKey != NULL)
  148. {
  149. RegCloseKey(m_hKey);
  150. m_hKey = NULL;
  151. }
  152. LONG lResult = RegOpenKeyEx(
  153. hKey, // handle of open key
  154. lpSubKey, // address of name of subkey to open
  155. 0 , // reserved
  156. access, // security access mask
  157. &m_hKey // address of handle of open key
  158. );
  159. if (lResult != ERROR_SUCCESS)
  160. {
  161. m_hKey = NULL;
  162. }
  163. return lResult;
  164. }
  165. DWORD CRegistry::DeleteValue (LPCTSTR lpValue)
  166. {
  167. ASSERT(lpValue);
  168. ASSERT(m_hKey);
  169. return RegDeleteValue(m_hKey, lpValue);
  170. }
  171. DWORD CRegistry::RecurseDeleteKey (LPCTSTR lpSubKey)
  172. {
  173. ASSERT(lpSubKey);
  174. ASSERT(m_hKey);
  175. CRegistry reg;
  176. DWORD dwError = reg.OpenKey(m_hKey, lpSubKey);
  177. if (dwError != ERROR_SUCCESS)
  178. return dwError;
  179. LPTSTR lpChildKey;
  180. DWORD dwSize;
  181. // we needn't/shouldn't use GetNextSubKey in this here
  182. // as we are deleting the key during the loop.
  183. while (ERROR_SUCCESS == reg.GetFirstSubKey(&lpChildKey, &dwSize))
  184. {
  185. VERIFY(reg.RecurseDeleteKey(lpChildKey) == ERROR_SUCCESS);
  186. }
  187. return RegDeleteKey(m_hKey, lpSubKey);
  188. }
  189. /*--------------------------------------------------------------------------------------------------------
  190. * DWORD ReadReg(LPCTSTR lpValue, LPBYTE *lppbyte, DWORD *pdw, DWORD dwDatatype)
  191. * Reads the registry used internally.
  192. * LPCTSTR lpValue - value to be read.
  193. * LPBYTE *lppbyte - address of the lpbyte at which to place the output buffer.
  194. * DWORD *pdw - address of dword in which size of the buffer (in bytes) is returned.
  195. * dword datatype - datatype you are expecting.
  196. * RETURNS error code.
  197. * -------------------------------------------------------------------------------------------------------*/
  198. DWORD CRegistry::ReadReg(LPCTSTR lpValue, LPBYTE *lppbyte, DWORD *pdw, DWORD dwDatatype)
  199. {
  200. ASSERT(lpValue);
  201. ASSERT(lppbyte);
  202. ASSERT(pdw);
  203. ASSERT(m_hKey != NULL);
  204. *pdw = 0;
  205. DWORD dwType;
  206. DWORD lResult = RegQueryValueEx(
  207. m_hKey, // handle of key to query
  208. lpValue, // address of name of value to query
  209. 0, // reserved
  210. &dwType, // address of buffer for value type
  211. 0, // address of data buffer
  212. pdw // address of data buffer size
  213. );
  214. if (lResult == ERROR_SUCCESS)
  215. {
  216. ASSERT(dwType == dwDatatype || dwType == REG_EXPAND_SZ);
  217. if (0 == Allocate(*pdw))
  218. return ERROR_OUTOFMEMORY;
  219. lResult = RegQueryValueEx(
  220. m_hKey, // handle of key to query
  221. lpValue, // address of name of value to query
  222. 0, // reserved
  223. &dwType, // address of buffer for value type
  224. m_pMemBlock, // address of data buffer
  225. pdw // address of data buffer size
  226. );
  227. ASSERT (ERROR_MORE_DATA != lResult);
  228. if (lResult == ERROR_SUCCESS)
  229. *lppbyte = m_pMemBlock;
  230. }
  231. return lResult;
  232. }
  233. /*--------------------------------------------------------------------------------------------------------
  234. * DWORD ReadRegString(LPCTSTR lpValue, LPTSTR *lppStr, DWORD *pdw)
  235. * Reads A string (REG_SZ) from the registry
  236. * LPCTSTR lpValue value to be read.
  237. * LPTSTR *lppStr - address of LPTSTR in which resultant buffer is returned. caller must copy
  238. * the buffer to immediately. caller must not use this buffer except for copying it.
  239. * caller must not write to this buffer.
  240. * DWORD *pdw - address of dword in which size of the buffer (in bytes) is returned.
  241. * RETURNS error code.
  242. * -------------------------------------------------------------------------------------------------------*/
  243. DWORD CRegistry::ReadRegString(LPCTSTR lpValue, LPTSTR *lppStr, DWORD *pdw)
  244. {
  245. return ReadReg(lpValue, (LPBYTE *)lppStr, pdw, REG_SZ);
  246. }
  247. /*--------------------------------------------------------------------------------------------------------
  248. * DWORD ReadRegDWord(LPCTSTR lpValue, DWORD *pdw)
  249. * Reads A string (REG_SZ) from the registry
  250. * LPCTSTR lpValue value to be read.
  251. * DWORD *pdw - address of dword in which the read dword returned.
  252. * RETURNS error code.
  253. * -------------------------------------------------------------------------------------------------------*/
  254. DWORD CRegistry::ReadRegDWord(LPCTSTR lpValue, DWORD *pdw)
  255. {
  256. ASSERT(pdw);
  257. DWORD dwSize;
  258. LPBYTE pByte;
  259. DWORD dwReturn = ReadReg(lpValue, &pByte, &dwSize, REG_DWORD);
  260. ASSERT(dwReturn != ERROR_SUCCESS || dwSize == sizeof(DWORD));
  261. if (dwReturn == ERROR_SUCCESS)
  262. *pdw = * LPDWORD(pByte);
  263. return dwReturn;
  264. }
  265. /*--------------------------------------------------------------------------------------------------------
  266. * DWORD ReadRegMultiString(LPCTSTR lpValue, LPTSTR *lppStr, DWORD *pdw)
  267. * Reads A string (REG_MULTI_SZ) from the registry
  268. * LPCTSTR lpValue value to be read.
  269. * LPTSTR *lppStr - address of LPTSTR in which resultant buffer is returned. caller must copy
  270. * the buffer to immediately. caller must not use this buffer except for copying it.
  271. * caller must not write to this buffer.
  272. * DWORD *pdw - address of dword in which size of the buffer (in bytes) is returned.
  273. * RETURNS error code.
  274. * -------------------------------------------------------------------------------------------------------*/
  275. DWORD CRegistry::ReadRegMultiString(LPCTSTR lpValue, LPTSTR *lppStr, DWORD *pdw)
  276. {
  277. return ReadReg(lpValue, (LPBYTE *)lppStr, pdw, REG_MULTI_SZ);
  278. }
  279. /*--------------------------------------------------------------------------------------------------------
  280. * DWORD ReadRegBinary(LPCTSTR lpValue, LPBYTE *lppByte, DWORD *pdw)
  281. * Reads A string (REG_MULTI_SZ) from the registry
  282. * LPCTSTR lpValue value to be read.
  283. * LPBYTE *lppByte - address of LPBYTE in which resultant buffer is returned. caller must copy
  284. * the buffer to immediately. caller must not use this buffer except for copying it.
  285. * caller must not write to this buffer.
  286. * DWORD *pdw - address of dword in which size of the buffer (in bytes) is returned.
  287. * RETURNS error code.
  288. * -------------------------------------------------------------------------------------------------------*/
  289. DWORD CRegistry::ReadRegBinary(LPCTSTR lpValue, LPBYTE *lppByte, DWORD *pdw)
  290. {
  291. return ReadReg(lpValue, lppByte, pdw, REG_BINARY);
  292. }
  293. /*--------------------------------------------------------------------------------------------------------
  294. * DWORD GetFirstSubKey(LPTSTR *lppStr, DWORD *pdw)
  295. * Reads a first subkey for the key
  296. * LPTSTR *lppStr - address of LPTSTR in which resultant buffer is returned. caller must copy
  297. * the buffer to immediately. caller must not use this buffer except for copying it.
  298. * caller must not write to this buffer.
  299. * used to enumerate the registry.
  300. * DWORD *pdw - address of dword in which size of the buffer (in bytes) is returned.
  301. * RETURNS error code.
  302. * -------------------------------------------------------------------------------------------------------*/
  303. DWORD CRegistry::GetFirstSubKey(LPTSTR *lppStr, DWORD *pdw)
  304. {
  305. ASSERT(lppStr);
  306. ASSERT(pdw);
  307. m_iEnumIndex = 0;
  308. return GetNextSubKey(lppStr, pdw);
  309. }
  310. /*--------------------------------------------------------------------------------------------------------
  311. * DWORD GetNextSubKey(LPTSTR *lppStr, DWORD *pdw
  312. * Reads the next subkey for the key
  313. * LPTSTR *lppStr - address of LPTSTR in which resultant buffer is returned. caller must copy
  314. * the buffer to immediately. caller must not use this buffer except for copying it.
  315. * caller must not write to this buffer.
  316. * used to enumerate the registry.
  317. * DWORD *pdw - address of dword in which size of the buffer (in bytes) is returned.
  318. * RETURNS error code.
  319. * -------------------------------------------------------------------------------------------------------*/
  320. DWORD CRegistry::GetNextSubKey(LPTSTR *lppStr, DWORD *pdw)
  321. {
  322. ASSERT(lppStr);
  323. ASSERT(pdw);
  324. ASSERT(m_hKey != NULL);
  325. ASSERT(m_iEnumIndex >= 0); // must call GetFirstSubKey first.
  326. *pdw = 1024;
  327. if (0 == Allocate(*pdw * sizeof(TCHAR)))
  328. return ERROR_NOT_ENOUGH_MEMORY;
  329. LONG lResult = RegEnumKeyEx(
  330. m_hKey, // handle of key to enumerate
  331. m_iEnumIndex, // index of subkey to enumerate
  332. (LPTSTR)m_pMemBlock, // address of buffer for subkey name
  333. pdw, // address for size of subkey buffer
  334. 0, // reserved
  335. NULL, // address of buffer for class string
  336. NULL, // address for size of class buffer
  337. NULL // address for time key last written to
  338. );
  339. (*pdw)++; // since null is not included in the size.
  340. if (ERROR_NO_MORE_ITEMS == lResult)
  341. return lResult;
  342. m_iEnumIndex++;
  343. if (lResult == ERROR_SUCCESS)
  344. *lppStr = (LPTSTR)m_pMemBlock;
  345. return lResult;
  346. }
  347. /*--------------------------------------------------------------------------------------------------------
  348. * DWORD GetFirstValue(LPTSTR *lppStr, DWORD *pdw, DWORD *pDataType)
  349. * Reads a first value for the key
  350. * LPTSTR *lppStr - address of LPTSTR in which resultant buffer is returned. caller must copy
  351. * the buffer to immediately. caller must not use this buffer except for copying it.
  352. * caller must not write to this buffer.
  353. * used to enumerate the registry.
  354. * DWORD *pdw - address of dword in which size of the buffer (in bytes) is returned.
  355. * DWORD *pDataType - datatype of the value is returned in this one.
  356. * RETURNS error code.
  357. * -------------------------------------------------------------------------------------------------------*/
  358. DWORD CRegistry::GetFirstValue(LPTSTR *lppStr, DWORD *pdw, DWORD *pDataType)
  359. {
  360. ASSERT(lppStr);
  361. ASSERT(pdw);
  362. ASSERT(pDataType);
  363. m_iEnumValueIndex = 0;
  364. return GetNextValue(lppStr, pdw, pDataType);
  365. }
  366. /*--------------------------------------------------------------------------------------------------------
  367. * DWORD GetNextValue(LPTSTR *lppStr, DWORD *pdw, DWORD *pDataType)
  368. * Reads a next value for the key
  369. * LPTSTR *lppStr - address of LPTSTR in which resultant buffer is returned. caller must copy
  370. * the buffer to immediately. caller must not use this buffer except for copying it.
  371. * caller must not write to this buffer.
  372. * used to enumerate the registry.
  373. * DWORD *pdw - address of dword in which size of the buffer (in bytes) is returned.
  374. * DWORD *pDataType - datatype of the value is returned in this one.
  375. * RETURNS error code.
  376. * -------------------------------------------------------------------------------------------------------*/
  377. DWORD CRegistry::GetNextValue(LPTSTR *lppStr, DWORD *pdw, DWORD *pDataType)
  378. {
  379. ASSERT(lppStr);
  380. ASSERT(pdw);
  381. ASSERT(pDataType);
  382. ASSERT(m_hKey != NULL);
  383. ASSERT(m_iEnumValueIndex >= 0); // must call GetFirstSubKey first.
  384. *pdw = 1024;
  385. if (0 == Allocate(*pdw * sizeof(TCHAR)))
  386. return ERROR_NOT_ENOUGH_MEMORY;
  387. LONG lResult = RegEnumValue(
  388. m_hKey, // handle of key to query
  389. m_iEnumValueIndex, // index of value to query
  390. (LPTSTR)m_pMemBlock, // address of buffer for value string
  391. pdw, // address for size of value buffer
  392. 0, // reserved
  393. pDataType, // address of buffer for type code
  394. NULL, // address of buffer for value data maks_todo : use this
  395. NULL // address for size of data buffer
  396. );
  397. (*pdw)++; // since null is not included in the size.
  398. if (ERROR_NO_MORE_ITEMS == lResult)
  399. return lResult;
  400. m_iEnumValueIndex++;
  401. if (lResult == ERROR_SUCCESS)
  402. *lppStr = (LPTSTR)m_pMemBlock;
  403. return lResult;
  404. }
  405. /*--------------------------------------------------------------------------------------------------------
  406. * DWORD WriteRegString(LPCTSTR lpValueName, LPCTSTR lpStr)
  407. * writes REG_SZ value into the registry
  408. * LPCTSTR lpValueName - value name to be written to
  409. * LPCTSTR lpStr - data to be written
  410. * RETURNS error code.
  411. * -------------------------------------------------------------------------------------------------------*/
  412. DWORD CRegistry::WriteRegString(LPCTSTR lpValueName, LPCTSTR lpStr)
  413. {
  414. ASSERT(m_hKey != NULL); // call setkey before calling this function.
  415. ASSERT(lpValueName);
  416. ASSERT(lpStr);
  417. DWORD dwSize = (_tcslen(lpStr) + 1) * sizeof(TCHAR) / sizeof(BYTE);
  418. return RegSetValueEx(
  419. m_hKey, // handle of key to set value for
  420. lpValueName, // address of value to set
  421. 0, // Reserved
  422. REG_SZ, // flag for value type
  423. (LPBYTE)lpStr, // address of value data
  424. dwSize // size of value data
  425. );
  426. }
  427. /*--------------------------------------------------------------------------------------------------------
  428. * DWORD WriteRegExpString(LPCTSTR lpValueName, LPCTSTR lpStr)
  429. * writes REG_EXPAND_SZ value into the registry
  430. * LPCTSTR lpValueName - value name to be written to
  431. * LPCTSTR lpStr - data to be written
  432. * RETURNS error code.
  433. * -------------------------------------------------------------------------------------------------------*/
  434. DWORD CRegistry::WriteRegExpString(LPCTSTR lpValueName, LPCTSTR lpStr)
  435. {
  436. ASSERT(m_hKey != NULL); // call setkey before calling this function.
  437. ASSERT(lpValueName);
  438. ASSERT(lpStr);
  439. DWORD dwSize = (_tcslen(lpStr) + 1) * sizeof(TCHAR) / sizeof(BYTE);
  440. return RegSetValueEx(
  441. m_hKey, // handle of key to set value for
  442. lpValueName, // address of value to set
  443. 0, // Reserved
  444. REG_EXPAND_SZ, // flag for value type
  445. (LPBYTE)lpStr, // address of value data
  446. dwSize // size of value data
  447. );
  448. }
  449. /*--------------------------------------------------------------------------------------------------------
  450. * DWORD WriteRegMultiString(LPCTSTR lpValueName, LPCTSTR lpStr, DWORD dwSize)
  451. * writes REG_MULTI_SZ value into the registry
  452. * LPCTSTR lpValueName - value name to be written to
  453. * LPCTSTR lpStr - data to be written
  454. * DWORD dwSize - size of data.
  455. * RETURNS error code.
  456. * -------------------------------------------------------------------------------------------------------*/
  457. DWORD CRegistry::WriteRegMultiString(LPCTSTR lpValueName, LPCTSTR lpStr, DWORD dwSize)
  458. {
  459. ASSERT(m_hKey != NULL); // call setkey before calling this function.
  460. ASSERT(lpValueName);
  461. ASSERT(lpStr);
  462. #ifdef DBG
  463. // lets make sure that the given size is right.
  464. LPCTSTR lpTemp = lpStr;
  465. DWORD rightsize = 0;
  466. while (_tcslen(lpTemp) > 0)
  467. {
  468. rightsize += _tcslen(lpTemp) + 1;
  469. lpTemp += _tcslen(lpTemp) + 1;
  470. }
  471. ASSERT(*lpTemp == 0); // final NULL.
  472. rightsize++; // account for final terminating null
  473. rightsize *= sizeof(TCHAR) / sizeof(BYTE); // size must be in bytes.
  474. ASSERT(dwSize == rightsize);
  475. #endif
  476. return RegSetValueEx(
  477. m_hKey, // handle of key to set value for
  478. lpValueName, // address of value to set
  479. 0, // Reserved
  480. REG_MULTI_SZ, // flag for value type
  481. (LPBYTE)lpStr, // address of value data
  482. dwSize // size of value data
  483. );
  484. }
  485. /*--------------------------------------------------------------------------------------------------------
  486. * DWORD WriteRegBinary (LPCTSTR lpValueName, LPBYTE lpData, DWORD dwSize)
  487. * writes REG_BINARY value into the registry
  488. * LPCTSTR lpValueName - value name to be written to
  489. * LPBYTE lpData - data to be written
  490. * DWORD dwSize - size of data.
  491. * RETURNS error code.
  492. * -------------------------------------------------------------------------------------------------------*/
  493. DWORD CRegistry::WriteRegBinary (LPCTSTR lpValueName, LPBYTE lpData, DWORD dwSize)
  494. {
  495. ASSERT(m_hKey != NULL); // call setkey before calling this function.
  496. ASSERT(lpValueName);
  497. ASSERT(lpData);
  498. ASSERT(dwSize > 0);
  499. return RegSetValueEx(
  500. m_hKey, // handle of key to set value for
  501. lpValueName, // address of value to set
  502. 0, // Reserved
  503. REG_BINARY, // flag for value type
  504. lpData, // address of value data
  505. dwSize // size of value data
  506. );
  507. }
  508. /*--------------------------------------------------------------------------------------------------------
  509. * DWORD WriteRegDWord(LPCTSTR lpValueName, DWORD dwValue)
  510. * writes REG_DWORD value into the registry
  511. * LPCTSTR lpValueName - value name to be written to
  512. * LPCTSTR dwValue - data to be written
  513. * RETURNS error code.
  514. * -------------------------------------------------------------------------------------------------------*/
  515. DWORD CRegistry::WriteRegDWord(LPCTSTR lpValueName, DWORD dwValue)
  516. {
  517. ASSERT(m_hKey != NULL); // call setkey before calling this function.
  518. ASSERT(lpValueName);
  519. return RegSetValueEx(
  520. m_hKey, // handle of key to set value for
  521. lpValueName, // address of value to set
  522. 0, // Reserved
  523. REG_DWORD, // flag for value type
  524. (LPBYTE)&dwValue, // address of value data
  525. sizeof(dwValue) // size of value data
  526. );
  527. }
  528. /*--------------------------------------------------------------------------------------------------------
  529. * DWORD ExistInMultiString (LPCTSTR lpValueName, LPCTSTR lpStr, BOOL *pbExists)
  530. * checks if given null terminated string exists in a multi_sz value
  531. * LPCTSTR lpValueName - value name to be checked
  532. * LPCTSTR lpCheckForStr - the value to be checked for
  533. * BOOL *pbExists - return. TRUE if exits.
  534. * RETURNS error code.
  535. * -------------------------------------------------------------------------------------------------------*/
  536. /*
  537. DWORD CRegistry::ExistInMultiString (LPCTSTR lpValueName, LPCTSTR lpCheckForStr, BOOL *pbExists)
  538. {
  539. ASSERT(m_hKey != NULL); // call setkey before calling this function.
  540. ASSERT(lpValueName);
  541. ASSERT(lpCheckForStr);
  542. ASSERT(*lpCheckForStr);
  543. ASSERT(pbExists);
  544. DWORD dwError = ERROR_SUCCESS;
  545. *pbExists = FALSE;
  546. LPTSTR szValue;
  547. DWORD dwSize;
  548. dwError = ReadRegMultiString(lpValueName, &szValue, dwSize);
  549. if (ERROR_SUCCESS == dwError)
  550. {
  551. LPCTSTR pTemp = szValue;
  552. while(_tcslen(pTemp) > 0 )
  553. {
  554. if (_tcscmp(pTemp, lpCheckForStr) == 0)
  555. {
  556. *pbExists = TRUE;
  557. break;
  558. }
  559. pTemp += _tcslen(pTemp) + 1; // point to the next string within the multistring.
  560. if ( DWORD(pTemp - szSuiteValue) > (dwSize / sizeof(TCHAR)))
  561. break; // temporary pointer passes the size of the szSuiteValue something is wrong with szSuiteValue.
  562. }
  563. }
  564. return dwError;
  565. ASSERT(FALSE);
  566. return ERROR_CALL_NOT_IMPLEMENTED;
  567. }
  568. */
  569. /*--------------------------------------------------------------------------------------------------------
  570. * DWORD AppendToMultiString (LPCTSTR lpValueName, LPCTSTR lpStr)
  571. * appends given string to a multistring value
  572. * LPCTSTR lpValueName - value name to be appended to
  573. * LPCTSTR lpStr - the value to be appended
  574. * RETURNS error code.
  575. * -------------------------------------------------------------------------------------------------------*/
  576. DWORD CRegistry::AppendToMultiString (LPCTSTR lpValueName, LPCTSTR lpStr)
  577. {
  578. ASSERT(m_hKey != NULL); // call setkey before calling this function.
  579. ASSERT(lpValueName);
  580. ASSERT(lpStr);
  581. ASSERT(*lpStr);
  582. return ERROR_CALL_NOT_IMPLEMENTED;
  583. }
  584. // copy the buffer immediately
  585. DWORD CRegistry::GetSecurity(PSECURITY_DESCRIPTOR *ppSec, SECURITY_INFORMATION SecurityInformation, DWORD *pdwSize)
  586. {
  587. ASSERT(m_hKey != NULL); // call setkey before calling this function.
  588. ASSERT(ppSec);
  589. ASSERT(pdwSize);
  590. DWORD dwError;
  591. PSECURITY_DESCRIPTOR pSecurityDescriptor = NULL;
  592. *pdwSize = 0; // we just want to get the right size during the first call.
  593. dwError = RegGetKeySecurity(
  594. m_hKey, // open handle of key to set
  595. SecurityInformation, // descriptor contents
  596. &pSecurityDescriptor, // address of descriptor for key
  597. pdwSize // address of size of buffer and descriptor
  598. );
  599. // this call can not succeed. as we have set the size = 0
  600. ASSERT(dwError != ERROR_SUCCESS);
  601. if (dwError != ERROR_INSUFFICIENT_BUFFER)
  602. {
  603. // something else has went wronng.
  604. // return the error code
  605. return dwError;
  606. }
  607. ASSERT(*pdwSize != 0);
  608. // now we have got the right size, allocate it.
  609. if (0 == Allocate(*pdwSize))
  610. return ERROR_OUTOFMEMORY;
  611. dwError = RegGetKeySecurity(
  612. m_hKey, // open handle of key to set
  613. SecurityInformation, // descriptor contents
  614. m_pMemBlock, // address of descriptor for key
  615. pdwSize // address of size of buffer and descriptor
  616. );
  617. ASSERT(dwError != ERROR_INSUFFICIENT_BUFFER);
  618. if (dwError == ERROR_SUCCESS)
  619. *ppSec = m_pMemBlock;
  620. return dwError;
  621. }
  622. DWORD CRegistry::SetSecurity(PSECURITY_DESCRIPTOR pSec, SECURITY_INFORMATION SecurityInformation)
  623. {
  624. ASSERT(m_hKey != NULL); // call setkey before calling this function.
  625. return RegSetKeySecurity(
  626. m_hKey, // open handle of key to set
  627. SecurityInformation, // descriptor contents
  628. pSec // address of descriptor for key
  629. );
  630. }
  631. // this function will fail miserably if the source and destination overlap.
  632. DWORD CRegistry::CopyTree(CRegistry &regSrc)
  633. {
  634. DWORD dwSize;
  635. LPTSTR szKey;
  636. LPTSTR szValue;
  637. DWORD dwError;
  638. if (ERROR_SUCCESS == (dwError = regSrc.GetFirstSubKey(&szKey, &dwSize)))
  639. {
  640. do
  641. {
  642. CRegistry regSrcKey;
  643. CRegistry regDstKey;
  644. if (ERROR_SUCCESS == (dwError = regSrcKey.OpenKey(regSrc, szKey)))
  645. {
  646. if (ERROR_SUCCESS == (dwError = regDstKey.CreateKey(m_hKey, szKey)))
  647. {
  648. regDstKey.CopyTree(regSrcKey);
  649. }
  650. else
  651. {
  652. LOGMESSAGE2(_T("Failed to create dest key <%s>, LastError = %d"), szKey, dwError);
  653. }
  654. }
  655. else
  656. {
  657. LOGMESSAGE2(_T("Failed to open src key <%s>, LastError = %d"), szKey, dwError);
  658. }
  659. }
  660. while (ERROR_SUCCESS == (dwError = regSrc.GetNextSubKey(&szKey, &dwSize)));
  661. }
  662. //
  663. // now copy values.
  664. //
  665. DWORD dwDataType;
  666. if (ERROR_SUCCESS == (dwError = regSrc.GetFirstValue(&szValue, &dwSize, &dwDataType)))
  667. {
  668. do
  669. {
  670. TCHAR *szValueName = new TCHAR[dwSize];
  671. if (!szValueName)
  672. break;
  673. _tcscpy(szValueName, szValue);
  674. LPBYTE pData;
  675. if (ERROR_SUCCESS == (dwError = regSrc.ReadReg(szValueName, &pData, &dwSize, dwDataType)))
  676. {
  677. dwError = RegSetValueEx(
  678. m_hKey, // handle of key to set value for
  679. szValueName, // address of value to set
  680. 0, // Reserved
  681. dwDataType, // flag for value type
  682. pData, // address of value data
  683. dwSize // size of value data
  684. );
  685. if (dwError != ERROR_SUCCESS)
  686. {
  687. LOGMESSAGE2(_T("Error Setting <%s>, Error = %d"), szValueName, dwError);
  688. }
  689. }
  690. else
  691. {
  692. LOGMESSAGE2(_T("Failed to Reading Value <%s>, Error = %d"), szValueName, dwError);
  693. }
  694. }
  695. while (ERROR_SUCCESS == regSrc.GetNextValue(&szValue, &dwSize, &dwDataType));
  696. }
  697. return TRUE;
  698. }
  699. #ifdef _Maks_AutoTest_
  700. //
  701. // make sure that CRegistry does not support
  702. // Copy constructor & assignment operator
  703. //
  704. void TestRegistry (CRegistry reg)
  705. {
  706. CRegistry reg2 = reg; // should get error for copy constructor
  707. CRegistry reg3(reg); // should get error for copy constructor
  708. CRegistry reg4;
  709. reg4 = reg; // should get error for = operator.
  710. TestRegistry(reg); // should get error for copy construtor
  711. }
  712. #endif // _Maks_AutoTest_
  713. // EOF