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.

865 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*/, LPCTSTR lpMachineName /* = NULL */)
  144. {
  145. LONG lResult;
  146. ASSERT(lpSubKey);
  147. ASSERT(*lpSubKey != '\\');
  148. LPTSTR szCompName = NULL;
  149. if (lpMachineName)
  150. {
  151. // if remote name is specified, hkey must be one of following.
  152. ASSERT(hKey == HKEY_LOCAL_MACHINE || hKey == HKEY_USERS || hKey == HKEY_PERFORMANCE_DATA);
  153. szCompName = new TCHAR[_tcslen(lpMachineName) + 3];
  154. if (!szCompName)
  155. return ERROR_OUTOFMEMORY;
  156. _tcscpy(szCompName, _T(""));
  157. if (*lpMachineName != '\\')
  158. {
  159. ASSERT(*(lpMachineName + 1) != '\\');
  160. _tcscpy(szCompName, _T("\\\\"));
  161. }
  162. _tcscat(szCompName, lpMachineName);
  163. // now connect to the remote computer.
  164. lResult = RegConnectRegistry (szCompName, hKey, &hKey);
  165. if (ERROR_SUCCESS != lResult)
  166. {
  167. delete [] szCompName;
  168. return lResult;
  169. }
  170. }
  171. if (m_hKey != NULL)
  172. {
  173. RegCloseKey(m_hKey);
  174. m_hKey = NULL;
  175. }
  176. lResult = RegOpenKeyEx(
  177. hKey, // handle of open key
  178. lpSubKey, // address of name of subkey to open
  179. 0 , // reserved
  180. access, // security access mask
  181. &m_hKey // address of handle of open key
  182. );
  183. if (lResult != ERROR_SUCCESS)
  184. {
  185. m_hKey = NULL;
  186. }
  187. // if we opened remote registry.. lets close the top level key
  188. if (szCompName)
  189. {
  190. RegCloseKey(hKey);
  191. delete [] szCompName;
  192. }
  193. return lResult;
  194. }
  195. DWORD CRegistry::DeleteValue (LPCTSTR lpValue)
  196. {
  197. ASSERT(lpValue);
  198. ASSERT(m_hKey);
  199. return RegDeleteValue(m_hKey, lpValue);
  200. }
  201. DWORD CRegistry::RecurseDeleteKey (LPCTSTR lpSubKey)
  202. {
  203. ASSERT(lpSubKey);
  204. ASSERT(m_hKey);
  205. CRegistry reg;
  206. DWORD dwError = reg.OpenKey(m_hKey, lpSubKey);
  207. if (dwError != ERROR_SUCCESS)
  208. return dwError;
  209. LPTSTR lpChildKey;
  210. DWORD dwSize;
  211. // we needn't/shouldn't use GetNextSubKey in this here
  212. // as we are deleting the key during the loop.
  213. while (ERROR_SUCCESS == reg.GetFirstSubKey(&lpChildKey, &dwSize))
  214. {
  215. VERIFY(reg.RecurseDeleteKey(lpChildKey) == ERROR_SUCCESS);
  216. }
  217. return RegDeleteKey(m_hKey, lpSubKey);
  218. }
  219. /*--------------------------------------------------------------------------------------------------------
  220. * DWORD ReadReg(LPCTSTR lpValue, LPBYTE *lppbyte, DWORD *pdw, DWORD dwDatatype)
  221. * Reads the registry used internally.
  222. * LPCTSTR lpValue - value to be read.
  223. * LPBYTE *lppbyte - address of the lpbyte at which to place the output buffer.
  224. * DWORD *pdw - address of dword in which size of the buffer (in bytes) is returned.
  225. * dword datatype - datatype you are expecting.
  226. * RETURNS error code.
  227. * -------------------------------------------------------------------------------------------------------*/
  228. DWORD CRegistry::ReadReg(LPCTSTR lpValue, LPBYTE *lppbyte, DWORD *pdw, DWORD dwDatatype)
  229. {
  230. ASSERT(lpValue);
  231. ASSERT(lppbyte);
  232. ASSERT(pdw);
  233. ASSERT(m_hKey != NULL);
  234. *pdw = 0;
  235. DWORD dwType;
  236. DWORD lResult = RegQueryValueEx(
  237. m_hKey, // handle of key to query
  238. lpValue, // address of name of value to query
  239. 0, // reserved
  240. &dwType, // address of buffer for value type
  241. 0, // address of data buffer
  242. pdw // address of data buffer size
  243. );
  244. if (lResult == ERROR_SUCCESS)
  245. {
  246. ASSERT(dwType == dwDatatype || dwType == REG_EXPAND_SZ);
  247. if (0 == Allocate(*pdw))
  248. return ERROR_OUTOFMEMORY;
  249. lResult = RegQueryValueEx(
  250. m_hKey, // handle of key to query
  251. lpValue, // address of name of value to query
  252. 0, // reserved
  253. &dwType, // address of buffer for value type
  254. m_pMemBlock, // address of data buffer
  255. pdw // address of data buffer size
  256. );
  257. ASSERT (ERROR_MORE_DATA != lResult);
  258. if (lResult == ERROR_SUCCESS)
  259. *lppbyte = m_pMemBlock;
  260. }
  261. return lResult;
  262. }
  263. /*--------------------------------------------------------------------------------------------------------
  264. * DWORD ReadRegString(LPCTSTR lpValue, LPTSTR *lppStr, DWORD *pdw)
  265. * Reads A string (REG_SZ) from the registry
  266. * LPCTSTR lpValue value to be read.
  267. * LPTSTR *lppStr - address of LPTSTR 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::ReadRegString(LPCTSTR lpValue, LPTSTR *lppStr, DWORD *pdw)
  274. {
  275. return ReadReg(lpValue, (LPBYTE *)lppStr, pdw, REG_SZ);
  276. }
  277. /*--------------------------------------------------------------------------------------------------------
  278. * DWORD ReadRegDWord(LPCTSTR lpValue, DWORD *pdw)
  279. * Reads A string (REG_SZ) from the registry
  280. * LPCTSTR lpValue value to be read.
  281. * DWORD *pdw - address of dword in which the read dword returned.
  282. * RETURNS error code.
  283. * -------------------------------------------------------------------------------------------------------*/
  284. DWORD CRegistry::ReadRegDWord(LPCTSTR lpValue, DWORD *pdw)
  285. {
  286. ASSERT(pdw);
  287. DWORD dwSize;
  288. LPBYTE pByte;
  289. DWORD dwReturn = ReadReg(lpValue, &pByte, &dwSize, REG_DWORD);
  290. ASSERT(dwReturn != ERROR_SUCCESS || dwSize == sizeof(DWORD));
  291. if (dwReturn == ERROR_SUCCESS)
  292. *pdw = * LPDWORD(pByte);
  293. return dwReturn;
  294. }
  295. /*--------------------------------------------------------------------------------------------------------
  296. * DWORD ReadRegMultiString(LPCTSTR lpValue, LPTSTR *lppStr, DWORD *pdw)
  297. * Reads A string (REG_MULTI_SZ) from the registry
  298. * LPCTSTR lpValue value to be read.
  299. * LPTSTR *lppStr - address of LPTSTR in which resultant buffer is returned. caller must copy
  300. * the buffer to immediately. caller must not use this buffer except for copying it.
  301. * caller must not write to this buffer.
  302. * DWORD *pdw - address of dword in which size of the buffer (in bytes) is returned.
  303. * RETURNS error code.
  304. * -------------------------------------------------------------------------------------------------------*/
  305. DWORD CRegistry::ReadRegMultiString(LPCTSTR lpValue, LPTSTR *lppStr, DWORD *pdw)
  306. {
  307. return ReadReg(lpValue, (LPBYTE *)lppStr, pdw, REG_MULTI_SZ);
  308. }
  309. /*--------------------------------------------------------------------------------------------------------
  310. * DWORD ReadRegBinary(LPCTSTR lpValue, LPBYTE *lppByte, DWORD *pdw)
  311. * Reads A string (REG_MULTI_SZ) from the registry
  312. * LPCTSTR lpValue value to be read.
  313. * LPBYTE *lppByte - address of LPBYTE 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. * DWORD *pdw - address of dword in which size of the buffer (in bytes) is returned.
  317. * RETURNS error code.
  318. * -------------------------------------------------------------------------------------------------------*/
  319. DWORD CRegistry::ReadRegBinary(LPCTSTR lpValue, LPBYTE *lppByte, DWORD *pdw)
  320. {
  321. return ReadReg(lpValue, lppByte, pdw, REG_BINARY);
  322. }
  323. /*--------------------------------------------------------------------------------------------------------
  324. * DWORD GetFirstSubKey(LPTSTR *lppStr, DWORD *pdw)
  325. * Reads a first subkey for the key
  326. * LPTSTR *lppStr - address of LPTSTR in which resultant buffer is returned. caller must copy
  327. * the buffer to immediately. caller must not use this buffer except for copying it.
  328. * caller must not write to this buffer.
  329. * used to enumerate the registry.
  330. * DWORD *pdw - address of dword in which size of the buffer (in bytes) is returned.
  331. * RETURNS error code.
  332. * -------------------------------------------------------------------------------------------------------*/
  333. DWORD CRegistry::GetFirstSubKey(LPTSTR *lppStr, DWORD *pdw)
  334. {
  335. ASSERT(lppStr);
  336. ASSERT(pdw);
  337. m_iEnumIndex = 0;
  338. return GetNextSubKey(lppStr, pdw);
  339. }
  340. /*--------------------------------------------------------------------------------------------------------
  341. * DWORD GetNextSubKey(LPTSTR *lppStr, DWORD *pdw
  342. * Reads the next subkey for the key
  343. * LPTSTR *lppStr - address of LPTSTR in which resultant buffer is returned. caller must copy
  344. * the buffer to immediately. caller must not use this buffer except for copying it.
  345. * caller must not write to this buffer.
  346. * used to enumerate the registry.
  347. * DWORD *pdw - address of dword in which size of the buffer (in bytes) is returned.
  348. * RETURNS error code.
  349. * -------------------------------------------------------------------------------------------------------*/
  350. DWORD CRegistry::GetNextSubKey(LPTSTR *lppStr, DWORD *pdw)
  351. {
  352. ASSERT(lppStr);
  353. ASSERT(pdw);
  354. ASSERT(m_hKey != NULL);
  355. ASSERT(m_iEnumIndex >= 0); // must call GetFirstSubKey first.
  356. *pdw = 1024;
  357. if (0 == Allocate(*pdw * sizeof(TCHAR)))
  358. return ERROR_NOT_ENOUGH_MEMORY;
  359. LONG lResult = RegEnumKeyEx(
  360. m_hKey, // handle of key to enumerate
  361. m_iEnumIndex, // index of subkey to enumerate
  362. (LPTSTR)m_pMemBlock, // address of buffer for subkey name
  363. pdw, // address for size of subkey buffer
  364. 0, // reserved
  365. NULL, // address of buffer for class string
  366. NULL, // address for size of class buffer
  367. NULL // address for time key last written to
  368. );
  369. (*pdw)++; // since null is not included in the size.
  370. if (ERROR_NO_MORE_ITEMS == lResult)
  371. return lResult;
  372. m_iEnumIndex++;
  373. if (lResult == ERROR_SUCCESS)
  374. *lppStr = (LPTSTR)m_pMemBlock;
  375. return lResult;
  376. }
  377. /*--------------------------------------------------------------------------------------------------------
  378. * DWORD GetFirstValue(LPTSTR *lppStr, DWORD *pdw, DWORD *pDataType)
  379. * Reads a first value for the key
  380. * LPTSTR *lppStr - address of LPTSTR in which resultant buffer is returned. caller must copy
  381. * the buffer to immediately. caller must not use this buffer except for copying it.
  382. * caller must not write to this buffer.
  383. * used to enumerate the registry.
  384. * DWORD *pdw - address of dword in which size of the buffer (in bytes) is returned.
  385. * DWORD *pDataType - datatype of the value is returned in this one.
  386. * RETURNS error code.
  387. * -------------------------------------------------------------------------------------------------------*/
  388. DWORD CRegistry::GetFirstValue(LPTSTR *lppStr, DWORD *pdw, DWORD *pDataType)
  389. {
  390. ASSERT(lppStr);
  391. ASSERT(pdw);
  392. ASSERT(pDataType);
  393. m_iEnumValueIndex = 0;
  394. return GetNextValue(lppStr, pdw, pDataType);
  395. }
  396. /*--------------------------------------------------------------------------------------------------------
  397. * DWORD GetNextValue(LPTSTR *lppStr, DWORD *pdw, DWORD *pDataType)
  398. * Reads a next value for the key
  399. * LPTSTR *lppStr - address of LPTSTR in which resultant buffer is returned. caller must copy
  400. * the buffer to immediately. caller must not use this buffer except for copying it.
  401. * caller must not write to this buffer.
  402. * used to enumerate the registry.
  403. * DWORD *pdw - address of dword in which size of the buffer (in bytes) is returned.
  404. * DWORD *pDataType - datatype of the value is returned in this one.
  405. * RETURNS error code.
  406. * -------------------------------------------------------------------------------------------------------*/
  407. DWORD CRegistry::GetNextValue(LPTSTR *lppStr, DWORD *pdw, DWORD *pDataType)
  408. {
  409. ASSERT(lppStr);
  410. ASSERT(pdw);
  411. ASSERT(pDataType);
  412. ASSERT(m_hKey != NULL);
  413. ASSERT(m_iEnumValueIndex >= 0); // must call GetFirstSubKey first.
  414. *pdw = 1024;
  415. if (0 == Allocate(*pdw * sizeof(TCHAR)))
  416. return ERROR_NOT_ENOUGH_MEMORY;
  417. LONG lResult = RegEnumValue(
  418. m_hKey, // handle of key to query
  419. m_iEnumValueIndex, // index of value to query
  420. (LPTSTR)m_pMemBlock, // address of buffer for value string
  421. pdw, // address for size of value buffer
  422. 0, // reserved
  423. pDataType, // address of buffer for type code
  424. NULL, // address of buffer for value data maks_todo : use this
  425. NULL // address for size of data buffer
  426. );
  427. (*pdw)++; // since null is not included in the size.
  428. if (ERROR_NO_MORE_ITEMS == lResult)
  429. return lResult;
  430. m_iEnumValueIndex++;
  431. if (lResult == ERROR_SUCCESS)
  432. *lppStr = (LPTSTR)m_pMemBlock;
  433. return lResult;
  434. }
  435. /*--------------------------------------------------------------------------------------------------------
  436. * DWORD WriteRegString(LPCTSTR lpValueName, LPCTSTR lpStr)
  437. * writes REG_SZ value into the registry
  438. * LPCTSTR lpValueName - value name to be written to
  439. * LPCTSTR lpStr - data to be written
  440. * RETURNS error code.
  441. * -------------------------------------------------------------------------------------------------------*/
  442. DWORD CRegistry::WriteRegString(LPCTSTR lpValueName, LPCTSTR lpStr)
  443. {
  444. ASSERT(m_hKey != NULL); // call setkey before calling this function.
  445. ASSERT(lpValueName);
  446. ASSERT(lpStr);
  447. DWORD dwSize = (_tcslen(lpStr) + 1) * sizeof(TCHAR) / sizeof(BYTE);
  448. return RegSetValueEx(
  449. m_hKey, // handle of key to set value for
  450. lpValueName, // address of value to set
  451. 0, // Reserved
  452. REG_SZ, // flag for value type
  453. (LPBYTE)lpStr, // address of value data
  454. dwSize // size of value data
  455. );
  456. }
  457. /*--------------------------------------------------------------------------------------------------------
  458. * DWORD WriteRegMultiString(LPCTSTR lpValueName, LPCTSTR lpStr, DWORD dwSize)
  459. * writes REG_MULTI_SZ value into the registry
  460. * LPCTSTR lpValueName - value name to be written to
  461. * LPCTSTR lpStr - data to be written
  462. * DWORD dwSize - size of data.
  463. * RETURNS error code.
  464. * -------------------------------------------------------------------------------------------------------*/
  465. DWORD CRegistry::WriteRegMultiString(LPCTSTR lpValueName, LPCTSTR lpStr, DWORD dwSize)
  466. {
  467. ASSERT(m_hKey != NULL); // call setkey before calling this function.
  468. ASSERT(lpValueName);
  469. ASSERT(lpStr);
  470. #ifdef DBG
  471. // lets make sure that the given size is right.
  472. LPCTSTR lpTemp = lpStr;
  473. DWORD rightsize = 0;
  474. while (_tcslen(lpTemp) > 0)
  475. {
  476. rightsize += _tcslen(lpTemp) + 1;
  477. lpTemp += _tcslen(lpTemp) + 1;
  478. }
  479. ASSERT(*lpTemp == 0); // final NULL.
  480. rightsize++; // account for final terminating null
  481. rightsize *= sizeof(TCHAR) / sizeof(BYTE); // size must be in bytes.
  482. ASSERT(dwSize == rightsize);
  483. #endif
  484. return RegSetValueEx(
  485. m_hKey, // handle of key to set value for
  486. lpValueName, // address of value to set
  487. 0, // Reserved
  488. REG_MULTI_SZ, // flag for value type
  489. (LPBYTE)lpStr, // address of value data
  490. dwSize // size of value data
  491. );
  492. }
  493. /*--------------------------------------------------------------------------------------------------------
  494. * DWORD WriteRegBinary (LPCTSTR lpValueName, LPBYTE lpData, DWORD dwSize)
  495. * writes REG_BINARY value into the registry
  496. * LPCTSTR lpValueName - value name to be written to
  497. * LPBYTE lpData - data to be written
  498. * DWORD dwSize - size of data.
  499. * RETURNS error code.
  500. * -------------------------------------------------------------------------------------------------------*/
  501. DWORD CRegistry::WriteRegBinary (LPCTSTR lpValueName, LPBYTE lpData, DWORD dwSize)
  502. {
  503. ASSERT(m_hKey != NULL); // call setkey before calling this function.
  504. ASSERT(lpValueName);
  505. ASSERT(lpData);
  506. ASSERT(dwSize > 0);
  507. return RegSetValueEx(
  508. m_hKey, // handle of key to set value for
  509. lpValueName, // address of value to set
  510. 0, // Reserved
  511. REG_BINARY, // flag for value type
  512. lpData, // address of value data
  513. dwSize // size of value data
  514. );
  515. }
  516. /*--------------------------------------------------------------------------------------------------------
  517. * DWORD WriteRegDWord(LPCTSTR lpValueName, DWORD dwValue)
  518. * writes REG_DWORD value into the registry
  519. * LPCTSTR lpValueName - value name to be written to
  520. * LPCTSTR dwValue - data to be written
  521. * RETURNS error code.
  522. * -------------------------------------------------------------------------------------------------------*/
  523. DWORD CRegistry::WriteRegDWord(LPCTSTR lpValueName, DWORD dwValue)
  524. {
  525. ASSERT(m_hKey != NULL); // call setkey before calling this function.
  526. ASSERT(lpValueName);
  527. return RegSetValueEx(
  528. m_hKey, // handle of key to set value for
  529. lpValueName, // address of value to set
  530. 0, // Reserved
  531. REG_DWORD, // flag for value type
  532. (LPBYTE)&dwValue, // address of value data
  533. sizeof(dwValue) // size of value data
  534. );
  535. }
  536. /*--------------------------------------------------------------------------------------------------------
  537. * DWORD ExistInMultiString (LPCTSTR lpValueName, LPCTSTR lpStr, BOOL *pbExists)
  538. * checks if given null terminated string exists in a multi_sz value
  539. * LPCTSTR lpValueName - value name to be checked
  540. * LPCTSTR lpCheckForStr - the value to be checked for
  541. * BOOL *pbExists - return. TRUE if exits.
  542. * RETURNS error code.
  543. * -------------------------------------------------------------------------------------------------------*/
  544. /*
  545. DWORD CRegistry::ExistInMultiString (LPCTSTR lpValueName, LPCTSTR lpCheckForStr, BOOL *pbExists)
  546. {
  547. ASSERT(m_hKey != NULL); // call setkey before calling this function.
  548. ASSERT(lpValueName);
  549. ASSERT(lpCheckForStr);
  550. ASSERT(*lpCheckForStr);
  551. ASSERT(pbExists);
  552. DWORD dwError = ERROR_SUCCESS;
  553. *pbExists = FALSE;
  554. LPTSTR szValue;
  555. DWORD dwSize;
  556. dwError = ReadRegMultiString(lpValueName, &szValue, dwSize);
  557. if (ERROR_SUCCESS == dwError)
  558. {
  559. LPCTSTR pTemp = szValue;
  560. while(_tcslen(pTemp) > 0 )
  561. {
  562. if (_tcscmp(pTemp, lpCheckForStr) == 0)
  563. {
  564. *pbExists = TRUE;
  565. break;
  566. }
  567. pTemp += _tcslen(pTemp) + 1; // point to the next string within the multistring.
  568. if ( DWORD(pTemp - szSuiteValue) > (dwSize / sizeof(TCHAR)))
  569. break; // temporary pointer passes the size of the szSuiteValue something is wrong with szSuiteValue.
  570. }
  571. }
  572. return dwError;
  573. ASSERT(FALSE);
  574. return ERROR_CALL_NOT_IMPLEMENTED;
  575. }
  576. */
  577. /*--------------------------------------------------------------------------------------------------------
  578. * DWORD AppendToMultiString (LPCTSTR lpValueName, LPCTSTR lpStr)
  579. * appends given string to a multistring value
  580. * LPCTSTR lpValueName - value name to be appended to
  581. * LPCTSTR lpStr - the value to be appended
  582. * RETURNS error code.
  583. * -------------------------------------------------------------------------------------------------------*/
  584. DWORD CRegistry::AppendToMultiString (LPCTSTR lpValueName, LPCTSTR lpStr)
  585. {
  586. ASSERT(m_hKey != NULL); // call setkey before calling this function.
  587. ASSERT(lpValueName);
  588. ASSERT(lpStr);
  589. ASSERT(*lpStr);
  590. return ERROR_CALL_NOT_IMPLEMENTED;
  591. }
  592. // copy the buffer immediately
  593. DWORD CRegistry::GetSecurity(PSECURITY_DESCRIPTOR *ppSec, SECURITY_INFORMATION SecurityInformation, DWORD *pdwSize)
  594. {
  595. ASSERT(m_hKey != NULL); // call setkey before calling this function.
  596. ASSERT(ppSec);
  597. ASSERT(pdwSize);
  598. DWORD dwError;
  599. PSECURITY_DESCRIPTOR pSecurityDescriptor = NULL;
  600. *pdwSize = 0; // we just want to get the right size during the first call.
  601. dwError = RegGetKeySecurity(
  602. m_hKey, // open handle of key to set
  603. SecurityInformation, // descriptor contents
  604. &pSecurityDescriptor, // address of descriptor for key
  605. pdwSize // address of size of buffer and descriptor
  606. );
  607. // this call can not succeed. as we have set the size = 0
  608. ASSERT(dwError != ERROR_SUCCESS);
  609. if (dwError != ERROR_INSUFFICIENT_BUFFER)
  610. {
  611. // something else has went wronng.
  612. // return the error code
  613. return dwError;
  614. }
  615. ASSERT(*pdwSize != 0);
  616. // now we have got the right size, allocate it.
  617. if (0 == Allocate(*pdwSize))
  618. return ERROR_OUTOFMEMORY;
  619. dwError = RegGetKeySecurity(
  620. m_hKey, // open handle of key to set
  621. SecurityInformation, // descriptor contents
  622. m_pMemBlock, // address of descriptor for key
  623. pdwSize // address of size of buffer and descriptor
  624. );
  625. ASSERT(dwError != ERROR_INSUFFICIENT_BUFFER);
  626. if (dwError == ERROR_SUCCESS)
  627. *ppSec = m_pMemBlock;
  628. return dwError;
  629. }
  630. DWORD CRegistry::SetSecurity(PSECURITY_DESCRIPTOR pSec, SECURITY_INFORMATION SecurityInformation)
  631. {
  632. ASSERT(m_hKey != NULL); // call setkey before calling this function.
  633. return RegSetKeySecurity(
  634. m_hKey, // open handle of key to set
  635. SecurityInformation, // descriptor contents
  636. pSec // address of descriptor for key
  637. );
  638. }
  639. // this function will fail miserably if the source and destination overlap.
  640. DWORD CRegistry::CopyTree(CRegistry &regSrc)
  641. {
  642. DWORD dwSize;
  643. LPTSTR szKey;
  644. LPTSTR szValue;
  645. DWORD dwError;
  646. if (ERROR_SUCCESS == (dwError = regSrc.GetFirstSubKey(&szKey, &dwSize)))
  647. {
  648. do
  649. {
  650. CRegistry regSrcKey;
  651. CRegistry regDstKey;
  652. if (ERROR_SUCCESS == (dwError = regSrcKey.OpenKey(regSrc, szKey)))
  653. {
  654. if (ERROR_SUCCESS == (dwError = regDstKey.CreateKey(m_hKey, szKey)))
  655. {
  656. regDstKey.CopyTree(regSrcKey);
  657. }
  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. }
  686. }
  687. while (ERROR_SUCCESS == regSrc.GetNextValue(&szValue, &dwSize, &dwDataType));
  688. }
  689. return TRUE;
  690. }
  691. DWORD CRegistry::WriteRegExString(LPCTSTR lpValueName, LPCTSTR lpStr)
  692. {
  693. ASSERT(m_hKey != NULL); // call setkey before calling this function.
  694. ASSERT(lpValueName);
  695. ASSERT(lpStr);
  696. DWORD dwSize = (_tcslen(lpStr) + 1) * sizeof(TCHAR) / sizeof(BYTE);
  697. return RegSetValueEx(
  698. m_hKey, // handle of key to set value for
  699. lpValueName, // address of value to set
  700. 0, // Reserved
  701. REG_EXPAND_SZ, // flag for value type
  702. (LPBYTE)lpStr, // address of value data
  703. dwSize // size of value data
  704. );
  705. }
  706. #ifdef _Maks_AutoTest_
  707. //
  708. // make sure that CRegistry does not support
  709. // Copy constructor & assignment operator
  710. //
  711. void TestRegistry (CRegistry reg)
  712. {
  713. CRegistry reg2 = reg; // should get error for copy constructor
  714. CRegistry reg3(reg); // should get error for copy constructor
  715. CRegistry reg4;
  716. reg4 = reg; // should get error for = operator.
  717. TestRegistry(reg); // should get error for copy construtor
  718. }
  719. #endif // _Maks_AutoTest_
  720. // EOF