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.

1340 lines
25 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1996 - 1999
  3. Module Name:
  4. Registry
  5. Abstract:
  6. This module implements the CRegistry Class, simplifying access to the
  7. Registry Database.
  8. Author:
  9. Doug Barlow (dbarlow) 7/15/1996
  10. Environment:
  11. Win32, C++ w/ Exceptions
  12. Notes:
  13. The only exceptions thrown are DWORDs, containing the error code.
  14. --*/
  15. #ifndef WIN32_LEAN_AND_MEAN
  16. #define WIN32_LEAN_AND_MEAN
  17. #endif
  18. #include <windows.h>
  19. #include "cspUtils.h"
  20. #define NTOHL HTONL
  21. static inline DWORD
  22. HTONL(
  23. DWORD dwInVal)
  24. {
  25. DWORD dwOutVal;
  26. LPBYTE pbIn = (LPBYTE)&dwInVal,
  27. pbOut = (LPBYTE)&dwOutVal;
  28. for (DWORD index = 0; index < sizeof(DWORD); index += 1)
  29. pbOut[sizeof(DWORD) - 1 - index] = pbIn[index];
  30. return dwOutVal;
  31. }
  32. //
  33. //==============================================================================
  34. //
  35. // CRegistry
  36. //
  37. /*++
  38. CRegistry:
  39. These routines provide for the construction and destruction of Objects of
  40. this class.
  41. Arguments:
  42. regBase - A CRegistry object to be used as a parent for this object.
  43. hBase - A Registry key to be the parent of this object.
  44. szName - The name of the Registry key, relative to the supplied parent.
  45. samDesired - The desired SAM.
  46. dwOptions - Any special creation optiopns.
  47. Throws:
  48. None. If the registry access fails, the error will be thrown on first use.
  49. Author:
  50. Doug Barlow (dbarlow) 7/15/1996
  51. --*/
  52. CRegistry::CRegistry(
  53. HKEY hBase,
  54. LPCTSTR szName,
  55. REGSAM samDesired,
  56. DWORD dwOptions,
  57. LPSECURITY_ATTRIBUTES lpSecurityAttributes)
  58. : m_bfResult()
  59. {
  60. m_hKey = NULL;
  61. m_lSts = ERROR_BADKEY;
  62. Open(hBase, szName, samDesired, dwOptions, lpSecurityAttributes);
  63. }
  64. CRegistry::CRegistry()
  65. {
  66. m_hKey = NULL;
  67. m_lSts = ERROR_BADKEY;
  68. }
  69. CRegistry::~CRegistry()
  70. {
  71. Close();
  72. }
  73. /*++
  74. Open:
  75. These methods allow a CRegistry object to attempt to access a given registry
  76. entry.
  77. Arguments:
  78. regBase - A CRegistry object to be used as a parent for this object.
  79. hBase - A Registry key to be the parent of this object.
  80. szName - The name of the Registry key, relative to the supplied parent.
  81. samDesired - The desired SAM.
  82. dwOptions - Any special creation optiopns.
  83. Return Value:
  84. None
  85. Throws:
  86. None -- errors are saved for follow-on operations, so that Open can be used
  87. safely in a constructor.
  88. Author:
  89. Doug Barlow (dbarlow) 12/2/1996
  90. --*/
  91. void CRegistry::Open(
  92. HKEY hBase,
  93. LPCTSTR szName,
  94. REGSAM samDesired,
  95. DWORD dwOptions,
  96. LPSECURITY_ATTRIBUTES lpSecurityAttributes)
  97. {
  98. Close();
  99. if (REG_OPTION_EXISTS == dwOptions)
  100. {
  101. m_lSts = RegOpenKeyEx(
  102. hBase,
  103. szName,
  104. 0,
  105. samDesired,
  106. &m_hKey);
  107. m_dwDisposition = REG_OPENED_EXISTING_KEY;
  108. }
  109. else
  110. m_lSts = RegCreateKeyEx(
  111. hBase,
  112. szName,
  113. 0,
  114. TEXT(""),
  115. dwOptions,
  116. samDesired,
  117. lpSecurityAttributes,
  118. &m_hKey,
  119. &m_dwDisposition);
  120. }
  121. /*++
  122. Close:
  123. Shut down a CRegistry object, making it available for follow-on opens.
  124. Arguments:
  125. None
  126. Return Value:
  127. None
  128. Author:
  129. Doug Barlow (dbarlow) 12/2/1996
  130. --*/
  131. void
  132. CRegistry::Close(
  133. void)
  134. {
  135. HRESULT hrSts;
  136. if (NULL != m_hKey)
  137. {
  138. hrSts = RegCloseKey(m_hKey);
  139. ASSERT(ERROR_SUCCESS == hrSts);
  140. m_hKey = NULL;
  141. }
  142. m_lSts = ERROR_BADKEY;
  143. m_bfResult.Empty();
  144. }
  145. /*++
  146. Status:
  147. This routine returns the status code from the construction routine. This is
  148. useful to check for errors prior to having them thrown.
  149. Arguments:
  150. fQuiet indicates whether or not to throw an error if the status is not
  151. ERROR_SUCCESS.
  152. Return Value:
  153. The status code from the creation.
  154. Author:
  155. Doug Barlow (dbarlow) 7/15/1996
  156. --*/
  157. LONG
  158. CRegistry::Status(
  159. BOOL fQuiet)
  160. const
  161. {
  162. if ((ERROR_SUCCESS != m_lSts) && !fQuiet)
  163. throw (DWORD)m_lSts;
  164. return m_lSts;
  165. }
  166. /*++
  167. Empty:
  168. This method cleans out the registry tree under the given key. All
  169. underlying keys and values are removed. This does it's best -- if an error
  170. occurs, the emptying operation stops, leaving the registry in an
  171. indeterminate state.
  172. Arguments:
  173. None
  174. Return Value:
  175. None
  176. Throws:
  177. Errors are thrown as DWORD status codes.
  178. Author:
  179. Doug Barlow (dbarlow) 1/16/1998
  180. --*/
  181. void
  182. CRegistry::Empty(
  183. void)
  184. {
  185. LPCTSTR szValue;
  186. LPCTSTR szKey;
  187. //
  188. // Go through all the values and delete them.
  189. //
  190. while (NULL != (szValue = Value(0)))
  191. DeleteValue(szValue, TRUE);
  192. #if 0 // Obsolete code
  193. //
  194. // Go through all the Keys and empty them.
  195. //
  196. DWORD dwIndex;
  197. for (dwIndex = 0; NULL != (szKey = Subkey(dwIndex)); dwIndex += 1)
  198. {
  199. CRegistry regEmpty;
  200. regEmpty.Open(*this, szKey);
  201. regEmpty.Empty();
  202. regEmpty.Close();
  203. }
  204. #endif
  205. //
  206. // Now delete all the keys.
  207. //
  208. while (NULL != (szKey = Subkey(0)))
  209. DeleteKey(szKey, TRUE);
  210. }
  211. /*++
  212. Copy:
  213. This method loads the current registry keys with all the subkeys and values
  214. from the supplied key. Current keys and values of this key are deleted.
  215. Arguments:
  216. regSrc supplies the source registry key from which values and keys will be
  217. loaded.
  218. Return Value:
  219. None
  220. Throws:
  221. Errors are thrown as DWORD status codes.
  222. Author:
  223. Doug Barlow (dbarlow) 1/16/1998
  224. --*/
  225. void
  226. CRegistry::Copy(
  227. CRegistry &regSrc)
  228. {
  229. LPCTSTR szValue;
  230. LPCTSTR szKey;
  231. DWORD dwIndex, dwType;
  232. CRegistry regSrcSubkey, regDstSubkey;
  233. CBuffer bfValue;
  234. //
  235. // Go through all the values and copy them.
  236. //
  237. for (dwIndex = 0; NULL != (szValue = regSrc.Value(dwIndex)); dwIndex += 1)
  238. {
  239. regSrc.GetValue(szValue, bfValue, &dwType);
  240. SetValue(szValue, bfValue.Value(), bfValue.Length(), dwType);
  241. }
  242. //
  243. // Now copy all the keys.
  244. //
  245. for (dwIndex = 0; NULL != (szKey = regSrc.Subkey(dwIndex)); dwIndex += 1)
  246. {
  247. regSrcSubkey.Open(regSrc, szKey, KEY_READ);
  248. regDstSubkey.Open(
  249. *this,
  250. szKey,
  251. KEY_ALL_ACCESS,
  252. REG_OPTION_NON_VOLATILE);
  253. regDstSubkey.Status();
  254. regDstSubkey.Copy(regSrcSubkey);
  255. regDstSubkey.Close();
  256. regSrcSubkey.Close();
  257. }
  258. }
  259. /*++
  260. DeleteKey:
  261. This method deletes a subkey from this key.
  262. Arguments:
  263. szKey supplies the name of the key to be deleted.
  264. fQuiet supplies whether or not to suppress errors.
  265. Return Value:
  266. None
  267. Throws:
  268. if fQuiet is FALSE, then any errors encountered are thrown as a DWORD.
  269. Author:
  270. Doug Barlow (dbarlow) 7/15/1996
  271. --*/
  272. void
  273. CRegistry::DeleteKey(
  274. LPCTSTR szKey,
  275. BOOL fQuiet)
  276. const
  277. {
  278. if (ERROR_SUCCESS == m_lSts)
  279. {
  280. try
  281. {
  282. CRegistry regSubkey(m_hKey, szKey);
  283. LPCTSTR szSubKey;
  284. if (ERROR_SUCCESS == regSubkey.Status(TRUE))
  285. {
  286. while (NULL != (szSubKey = regSubkey.Subkey(0)))
  287. regSubkey.DeleteKey(szSubKey, fQuiet);
  288. }
  289. }
  290. catch (DWORD dwError)
  291. {
  292. if (!fQuiet)
  293. throw dwError;
  294. }
  295. LONG lSts = RegDeleteKey(m_hKey, szKey);
  296. if ((ERROR_SUCCESS != lSts) && !fQuiet)
  297. throw (DWORD)lSts;
  298. }
  299. else if (!fQuiet)
  300. throw (DWORD)m_lSts;
  301. }
  302. /*++
  303. DeleteValue:
  304. This method deletes a Value from this key.
  305. Arguments:
  306. szValue supplies the name of the Value to be deleted.
  307. fQuiet supplies whether or not to suppress errors.
  308. Return Value:
  309. None
  310. Throws:
  311. if fQuiet is FALSE, then any errors encountered are thrown as a DWORD.
  312. Author:
  313. Doug Barlow (dbarlow) 7/15/1996
  314. --*/
  315. void
  316. CRegistry::DeleteValue(
  317. LPCTSTR szValue,
  318. BOOL fQuiet)
  319. const
  320. {
  321. LONG lSts;
  322. if (fQuiet)
  323. {
  324. if (ERROR_SUCCESS == m_lSts)
  325. lSts = RegDeleteValue(m_hKey, szValue);
  326. }
  327. else
  328. {
  329. if (ERROR_SUCCESS != m_lSts)
  330. throw (DWORD)m_lSts;
  331. lSts = RegDeleteValue(m_hKey, szValue);
  332. if (ERROR_SUCCESS != lSts)
  333. throw (DWORD)lSts;
  334. }
  335. }
  336. /*++
  337. Subkey:
  338. This method allows for iterating over the names of the subkeys of this key.
  339. Arguments:
  340. dwIndex supplies the index into the set of subkeys.
  341. Return Value:
  342. The name of the indexed subkey, or NULL if none exists.
  343. Throws:
  344. Any error other than ERROR_NO_MORE_ITEMS is thrown.
  345. Author:
  346. Doug Barlow (dbarlow) 7/15/1996
  347. --*/
  348. LPCTSTR
  349. CRegistry::Subkey(
  350. DWORD dwIndex)
  351. {
  352. LONG lSts;
  353. DWORD dwLen;
  354. LPCTSTR szResult = NULL;
  355. BOOL fDone = FALSE;
  356. FILETIME ftLastWrite;
  357. if (ERROR_SUCCESS != m_lSts)
  358. throw (DWORD)m_lSts;
  359. m_bfResult.Space(128);
  360. while (!fDone)
  361. {
  362. dwLen = m_bfResult.Space() / sizeof(TCHAR);
  363. lSts = RegEnumKeyEx(
  364. m_hKey,
  365. dwIndex,
  366. (LPTSTR)m_bfResult.Access(),
  367. &dwLen,
  368. NULL,
  369. NULL,
  370. NULL,
  371. &ftLastWrite);
  372. switch (lSts)
  373. {
  374. case ERROR_SUCCESS:
  375. m_bfResult.Length((dwLen + 1) * sizeof(TCHAR));
  376. szResult = (LPCTSTR)m_bfResult.Value();
  377. fDone = TRUE;
  378. break;
  379. case ERROR_NO_MORE_ITEMS:
  380. szResult = NULL;
  381. fDone = TRUE;
  382. break;
  383. case ERROR_MORE_DATA:
  384. m_bfResult.Space((dwLen + 1) * sizeof(TCHAR));
  385. continue;
  386. default:
  387. throw (DWORD)lSts;
  388. }
  389. }
  390. return szResult;
  391. }
  392. /*++
  393. Value:
  394. This method allows for iterating over the names of the Values of this key.
  395. Arguments:
  396. dwIndex supplies the index into the set of Values.
  397. pdwType receives the type of the entry. This parameter may be NULL.
  398. Return Value:
  399. The name of the indexed Value, or NULL if none exists.
  400. Throws:
  401. Any error other than ERROR_NO_MORE_ITEMS is thrown.
  402. Author:
  403. Doug Barlow (dbarlow) 7/15/1996
  404. --*/
  405. LPCTSTR
  406. CRegistry::Value(
  407. DWORD dwIndex,
  408. LPDWORD pdwType)
  409. {
  410. LONG lSts;
  411. DWORD dwLen, dwType;
  412. LPCTSTR szResult = NULL;
  413. BOOL fDone = FALSE;
  414. if (ERROR_SUCCESS != m_lSts)
  415. throw (DWORD)m_lSts;
  416. m_bfResult.Space(128); // Force it to not be zero length.
  417. while (!fDone)
  418. {
  419. dwLen = m_bfResult.Space() / sizeof(TCHAR);
  420. lSts = RegEnumValue(
  421. m_hKey,
  422. dwIndex,
  423. (LPTSTR)m_bfResult.Access(),
  424. &dwLen,
  425. NULL,
  426. &dwType,
  427. NULL,
  428. NULL);
  429. switch (lSts)
  430. {
  431. case ERROR_SUCCESS:
  432. m_bfResult.Length((dwLen + 1) * sizeof(TCHAR));
  433. if (NULL != pdwType)
  434. *pdwType = dwType;
  435. szResult = (LPCTSTR)m_bfResult.Value();
  436. fDone = TRUE;
  437. break;
  438. case ERROR_NO_MORE_ITEMS:
  439. szResult = NULL;
  440. fDone = TRUE;
  441. break;
  442. case ERROR_MORE_DATA:
  443. if (dwLen == m_bfResult.Space())
  444. throw (DWORD)ERROR_INSUFFICIENT_BUFFER; // Won't tell us how big.
  445. m_bfResult.Space((dwLen + 1) * sizeof(TCHAR));
  446. break;
  447. default:
  448. throw (DWORD)lSts;
  449. }
  450. }
  451. return szResult;
  452. }
  453. /*++
  454. GetValue:
  455. These methods provide access to the values of the Value entries.
  456. Arguments:
  457. szKeyValue supplies the name of the Value entry to get.
  458. pszValue receives the value of the entry as a string.
  459. tzValue receives the value of the entry as a string.
  460. pdwValue receives the value of the entry as a DWORD.
  461. ppbValue receives the value of the entry as a Binary string.
  462. pcbLength receives the length of the entry when it's a binary string.
  463. pdwType receives the type of the registry entry.
  464. Return Value:
  465. None
  466. Throws:
  467. Any error encountered.
  468. Author:
  469. Doug Barlow (dbarlow) 7/15/1996
  470. --*/
  471. void
  472. CRegistry::GetValue(
  473. LPCTSTR szKeyValue,
  474. CBuffer &bfValue,
  475. LPDWORD pdwType)
  476. {
  477. LONG lSts;
  478. DWORD dwLen, dwType = 0;
  479. BOOL fDone = FALSE;
  480. if (ERROR_SUCCESS != m_lSts)
  481. throw (DWORD)m_lSts;
  482. while (!fDone)
  483. {
  484. dwLen = bfValue.Space();
  485. lSts = RegQueryValueEx(
  486. m_hKey,
  487. szKeyValue,
  488. NULL,
  489. &dwType,
  490. bfValue.Access(),
  491. &dwLen);
  492. switch (lSts)
  493. {
  494. case ERROR_SUCCESS:
  495. if (0 != bfValue.Space())
  496. {
  497. bfValue.Length(dwLen);
  498. fDone = TRUE;
  499. break;
  500. }
  501. // else fall through intentionally
  502. case ERROR_MORE_DATA:
  503. bfValue.Space(dwLen);
  504. break;
  505. default:
  506. throw (DWORD)lSts;
  507. }
  508. }
  509. if (NULL != pdwType)
  510. *pdwType = dwType;
  511. }
  512. void
  513. CRegistry::GetValue(
  514. LPCTSTR szKeyValue,
  515. LPTSTR *pszValue,
  516. LPDWORD pdwType)
  517. {
  518. DWORD dwLen, dwType;
  519. TCHAR chTmp;
  520. CBuffer bfUnexpanded;
  521. LONG lSts;
  522. dwLen = 0;
  523. lSts = RegQueryValueEx(
  524. m_hKey,
  525. szKeyValue,
  526. NULL,
  527. &dwType,
  528. NULL,
  529. &dwLen);
  530. if (ERROR_SUCCESS != lSts)
  531. throw (DWORD)lSts;
  532. switch (dwType)
  533. {
  534. case REG_EXPAND_SZ:
  535. bfUnexpanded.Space(dwLen);
  536. GetValue(szKeyValue, bfUnexpanded, &dwType);
  537. dwLen = ExpandEnvironmentStrings(
  538. (LPTSTR)bfUnexpanded.Value(),
  539. &chTmp,
  540. 0);
  541. if (0 == dwLen)
  542. throw GetLastError();
  543. m_bfResult.Space(dwLen * sizeof(TCHAR));
  544. dwLen = ExpandEnvironmentStrings(
  545. (LPTSTR)bfUnexpanded.Value(),
  546. (LPTSTR)m_bfResult.Access(),
  547. dwLen);
  548. if (0 == dwLen)
  549. throw GetLastError();
  550. m_bfResult.Length(dwLen * sizeof(TCHAR));
  551. break;
  552. case REG_BINARY:
  553. case REG_MULTI_SZ:
  554. case REG_SZ:
  555. m_bfResult.Space(dwLen);
  556. GetValue(szKeyValue, m_bfResult, &dwType);
  557. break;
  558. default:
  559. throw (DWORD)ERROR_BAD_FORMAT;
  560. }
  561. *pszValue = (LPTSTR)m_bfResult.Value();
  562. if (NULL != pdwType)
  563. *pdwType = dwType;
  564. }
  565. void
  566. CRegistry::GetValue(
  567. LPCTSTR szKeyValue,
  568. LPDWORD pdwValue,
  569. LPDWORD pdwType)
  570. const
  571. {
  572. LONG lSts;
  573. DWORD dwLen, dwType;
  574. CBuffer szExpanded;
  575. if (ERROR_SUCCESS != m_lSts)
  576. throw (DWORD)m_lSts;
  577. dwLen = sizeof(DWORD);
  578. lSts = RegQueryValueEx(
  579. m_hKey,
  580. szKeyValue,
  581. NULL,
  582. &dwType,
  583. (LPBYTE)pdwValue,
  584. &dwLen);
  585. if (ERROR_SUCCESS != lSts)
  586. throw (DWORD)lSts;
  587. switch (dwType)
  588. {
  589. case REG_DWORD_BIG_ENDIAN:
  590. *pdwValue = NTOHL(*pdwValue);
  591. break;
  592. case REG_DWORD:
  593. // case REG_DWORD_LITTLE_ENDIAN:
  594. break;
  595. default:
  596. throw (DWORD)ERROR_BAD_FORMAT;
  597. }
  598. if (NULL != pdwType)
  599. *pdwType = dwType;
  600. }
  601. void
  602. CRegistry::GetValue(
  603. LPCTSTR szKeyValue,
  604. LPBYTE *ppbValue,
  605. LPDWORD pcbLength,
  606. LPDWORD pdwType)
  607. {
  608. DWORD dwType;
  609. GetValue(szKeyValue, m_bfResult, &dwType);
  610. *ppbValue = m_bfResult;
  611. *pcbLength = m_bfResult.Length();
  612. if (NULL != pdwType)
  613. *pdwType = dwType;
  614. }
  615. /*++
  616. SetValue:
  617. These methods provide write access to the values of the Value entries.
  618. Arguments:
  619. szKeyValue supplies the name of the Value entry to set.
  620. szValue supplies the new value of the entry as a string.
  621. dwValue supplies the new value of the entry as a DWORD.
  622. pbValue supplies the new value of the entry as a Binary string.
  623. cbLength supplies the length of the entry when it's a binary string.
  624. dwType supplies the registry type value.
  625. Return Value:
  626. None
  627. Throws:
  628. Any error encountered.
  629. Author:
  630. Doug Barlow (dbarlow) 7/15/1996
  631. --*/
  632. void
  633. CRegistry::SetValue(
  634. LPCTSTR szKeyValue,
  635. LPCTSTR szValue,
  636. DWORD dwType)
  637. const
  638. {
  639. LONG lSts;
  640. if (ERROR_SUCCESS != m_lSts)
  641. throw (DWORD)m_lSts;
  642. lSts = RegSetValueEx(
  643. m_hKey,
  644. szKeyValue,
  645. 0,
  646. dwType,
  647. (LPBYTE)szValue,
  648. (lstrlen(szValue) + 1) * sizeof(TCHAR));
  649. if (ERROR_SUCCESS != lSts)
  650. throw (DWORD)lSts;
  651. }
  652. void
  653. CRegistry::SetValue(
  654. LPCTSTR szKeyValue,
  655. DWORD dwValue,
  656. DWORD dwType)
  657. const
  658. {
  659. LONG lSts;
  660. if (ERROR_SUCCESS != m_lSts)
  661. throw (DWORD)m_lSts;
  662. if (REG_DWORD_BIG_ENDIAN == dwType)
  663. dwValue = HTONL(dwValue);
  664. lSts = RegSetValueEx(
  665. m_hKey,
  666. szKeyValue,
  667. 0,
  668. dwType,
  669. (LPBYTE)&dwValue,
  670. sizeof(DWORD));
  671. if (ERROR_SUCCESS != lSts)
  672. throw (DWORD)lSts;
  673. }
  674. void
  675. CRegistry::SetValue(
  676. LPCTSTR szKeyValue,
  677. LPCBYTE pbValue,
  678. DWORD cbLength,
  679. DWORD dwType)
  680. const
  681. {
  682. LONG lSts;
  683. if (ERROR_SUCCESS != m_lSts)
  684. throw (DWORD)m_lSts;
  685. lSts = RegSetValueEx(
  686. m_hKey,
  687. szKeyValue,
  688. 0,
  689. dwType,
  690. pbValue,
  691. cbLength);
  692. if (ERROR_SUCCESS != lSts)
  693. throw (DWORD)lSts;
  694. }
  695. /*++
  696. GetStringValue:
  697. This is an alternate mechanism for obtaining a string value.
  698. Arguments:
  699. szKeyValue supplies the name of the Key Value to obtain.
  700. pdwType, if non-null, receives the type of registry entry.
  701. Return Value:
  702. The value of the registry entry as a string pointer.
  703. Throws:
  704. Any errors encountered.
  705. Author:
  706. Doug Barlow (dbarlow) 7/16/1996
  707. --*/
  708. LPCTSTR
  709. CRegistry::GetStringValue(
  710. LPCTSTR szKeyValue,
  711. LPDWORD pdwType)
  712. {
  713. LPTSTR szResult;
  714. GetValue(szKeyValue, &szResult, pdwType);
  715. return szResult;
  716. }
  717. /*++
  718. GetNumericValue:
  719. This is an alternate mechanism for obtaining a numeric value.
  720. Arguments:
  721. szKeyValue supplies the name of the Key Value to obtain.
  722. pdwType, if non-null, receives the type of registry entry.
  723. Return Value:
  724. The value of the registry entry as a DWORD.
  725. Throws:
  726. Any errors encountered.
  727. Author:
  728. Doug Barlow (dbarlow) 7/16/1996
  729. --*/
  730. DWORD
  731. CRegistry::GetNumericValue(
  732. LPCTSTR szKeyValue,
  733. LPDWORD pdwType)
  734. const
  735. {
  736. DWORD dwResult;
  737. GetValue(szKeyValue, &dwResult, pdwType);
  738. return dwResult;
  739. }
  740. /*++
  741. GetBinaryValue:
  742. This is an alternate mechanism for obtaining a binary value.
  743. Arguments:
  744. szKeyValue supplies the name of the Key Value to obtain.
  745. pdwType, if non-null, receives the type of registry entry.
  746. Return Value:
  747. The value of the registry entry as a binary pointer.
  748. Throws:
  749. Any errors encountered.
  750. Author:
  751. Doug Barlow (dbarlow) 7/16/1996
  752. --*/
  753. LPCBYTE
  754. CRegistry::GetBinaryValue(
  755. LPCTSTR szKeyValue,
  756. LPDWORD pcbLength,
  757. LPDWORD pdwType)
  758. {
  759. LPBYTE pbResult;
  760. DWORD cbLength;
  761. GetValue(szKeyValue, &pbResult, &cbLength, pdwType);
  762. if (NULL != pcbLength)
  763. *pcbLength = cbLength;
  764. return pbResult;
  765. }
  766. /*++
  767. GetValueLength:
  768. This routine is designed to work in conjunction with GetBinaryValue, but may
  769. have other uses as well. It returns the length of the internal storage
  770. area, in bytes. Note DWORDs are not stored internally, so this value will
  771. not represent the size of a DWORD following a GetNumericValue call.
  772. Arguments:
  773. none
  774. Return Value:
  775. The length of the internal storage buffer, in bytes.
  776. Throws:
  777. Any errors encountered.
  778. Author:
  779. Doug Barlow (dbarlow) 7/16/1996
  780. --*/
  781. DWORD
  782. CRegistry::GetValueLength(
  783. void)
  784. const
  785. {
  786. if (ERROR_SUCCESS != m_lSts)
  787. throw (DWORD)m_lSts;
  788. return m_bfResult.Length();
  789. }
  790. /*++
  791. ValueExists:
  792. This routine tests for the existance of a given value, and optionally
  793. returns its type and length.
  794. Arguments:
  795. none
  796. Return Value:
  797. A boolean indication as to whether or not the value exists.
  798. Throws:
  799. Any errors encountered.
  800. Author:
  801. Doug Barlow (dbarlow) 7/16/1996
  802. --*/
  803. BOOL
  804. CRegistry::ValueExists(
  805. LPCTSTR szKeyValue,
  806. LPDWORD pcbLength,
  807. LPDWORD pdwType)
  808. const
  809. {
  810. LONG lSts;
  811. DWORD dwLen, dwType;
  812. BOOL fResult = FALSE;
  813. if (ERROR_SUCCESS != m_lSts)
  814. throw (DWORD)m_lSts;
  815. dwLen = 0;
  816. lSts = RegQueryValueEx(
  817. m_hKey,
  818. szKeyValue,
  819. NULL,
  820. &dwType,
  821. NULL,
  822. &dwLen);
  823. if (ERROR_SUCCESS == lSts)
  824. {
  825. if (NULL != pcbLength)
  826. *pcbLength = dwLen;
  827. if (NULL != pdwType)
  828. *pdwType = dwType;
  829. fResult = TRUE;
  830. }
  831. return fResult;
  832. }
  833. /*++
  834. GetDisposition:
  835. This routine returns the disposition of creation.
  836. Arguments:
  837. none
  838. Return Value:
  839. The return disposition flag from creating the registry entry.
  840. Throws:
  841. Any errors encountered.
  842. Author:
  843. Doug Barlow (dbarlow) 7/16/1996
  844. --*/
  845. DWORD
  846. CRegistry::GetDisposition(
  847. void)
  848. const
  849. {
  850. if (ERROR_SUCCESS != m_lSts)
  851. throw (DWORD)m_lSts;
  852. return m_dwDisposition;
  853. }
  854. #if 0 // No Multi-string support yet...
  855. /*++
  856. SetMultiStringValue:
  857. This method simplifies the work of adding a MultiString value to the
  858. registry.
  859. Arguments:
  860. szKeyValue supplies the name of the Value entry to set.
  861. mszValue supplies the new value of the entry as a multi-string.
  862. dwType supplies the registry type value.
  863. Return Value:
  864. None
  865. Throws:
  866. Any errors encountered as a DWORD status value.
  867. Author:
  868. Doug Barlow (dbarlow) 11/6/1996
  869. --*/
  870. void
  871. CRegistry::SetMultiStringValue(
  872. LPCTSTR szKeyValue,
  873. LPCTSTR mszValue,
  874. DWORD dwType)
  875. const
  876. {
  877. LONG lSts;
  878. if (ERROR_SUCCESS != m_lSts)
  879. throw (DWORD)m_lSts;
  880. lSts = RegSetValueEx(
  881. m_hKey,
  882. szKeyValue,
  883. 0,
  884. dwType,
  885. (LPBYTE)mszValue,
  886. MStrLen(mszValue) * sizeof(TCHAR));
  887. if (ERROR_SUCCESS != lSts)
  888. throw (DWORD)lSts;
  889. }
  890. /*++
  891. GetMultiStringValue:
  892. This method obtains a multi-string value from the registry.
  893. Arguments:
  894. szKeyValue supplies the name of the Key Value to obtain.
  895. pdwType, if non-null, receives the type of registry entry.
  896. Return Value:
  897. The registry value, as a multi-string.
  898. Throws:
  899. Any errors encountered as a DWORD status value.
  900. Author:
  901. Doug Barlow (dbarlow) 11/6/1996
  902. --*/
  903. LPCTSTR
  904. CRegistry::GetMultiStringValue(
  905. LPCTSTR szKeyValue,
  906. LPDWORD pdwType)
  907. {
  908. LPTSTR szResult;
  909. GetValue(szKeyValue, &szResult, pdwType);
  910. return szResult;
  911. }
  912. #endif
  913. /*++
  914. SetAcls:
  915. This method sets security attributes for a single key, or an entire key
  916. branch.
  917. Arguments:
  918. SecurityInformation supplies the SECURITY_INFORMATION value (see
  919. RegSetKeySecurity in the SDK documentation).
  920. pSecurityDescriptor supplies the SECURITY_DESCRIPTOR value (see
  921. RegSetKeySecurity in the SDK documentation).
  922. fRecurse supplies an indicator as to whether to just set the ACL on this
  923. key (FALSE), or this key and all subkeys (TRUE).
  924. Return Value:
  925. None
  926. Throws:
  927. Errors are thrown as DWORD status codes.
  928. Author:
  929. Doug Barlow (dbarlow) 11/10/1998
  930. --*/
  931. void
  932. CRegistry::SetAcls(
  933. IN SECURITY_INFORMATION SecurityInformation,
  934. IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
  935. IN BOOL fRecurse)
  936. {
  937. LONG lSts;
  938. if (ERROR_SUCCESS != m_lSts)
  939. throw (DWORD)m_lSts;
  940. lSts = RegSetKeySecurity(
  941. m_hKey,
  942. SecurityInformation,
  943. pSecurityDescriptor);
  944. if (ERROR_SUCCESS != lSts)
  945. throw (DWORD)lSts;
  946. if (fRecurse)
  947. {
  948. CRegistry regSub;
  949. LPCTSTR szSubKey;
  950. DWORD dwIndex;
  951. for (dwIndex = 0;
  952. NULL != (szSubKey = Subkey(dwIndex));
  953. dwIndex += 1)
  954. {
  955. regSub.Open(m_hKey, szSubKey);
  956. regSub.SetAcls(
  957. SecurityInformation,
  958. pSecurityDescriptor);
  959. regSub.Close();
  960. }
  961. }
  962. }