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.

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