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.

1331 lines
24 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 "SCardLib.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.Reset();
  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.Access(), 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.Presize(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.Resize((dwLen + 1) * sizeof(TCHAR), TRUE);
  376. szResult = (LPCTSTR)m_bfResult.Access();
  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.Presize((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.Presize(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.Resize((dwLen + 1) * sizeof(TCHAR), TRUE);
  433. if (NULL != pdwType)
  434. *pdwType = dwType;
  435. szResult = (LPCTSTR)m_bfResult.Access();
  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.Presize((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. pdwValue receives the value of the entry as a DWORD.
  460. ppbValue receives the value of the entry as a Binary string.
  461. pcbLength receives the length of the entry when it's a binary string.
  462. pdwType receives the type of the registry entry.
  463. Return Value:
  464. None
  465. Throws:
  466. Any error encountered.
  467. Author:
  468. Doug Barlow (dbarlow) 7/15/1996
  469. --*/
  470. void
  471. CRegistry::GetValue(
  472. LPCTSTR szKeyValue,
  473. CBuffer &bfValue,
  474. LPDWORD pdwType)
  475. {
  476. LONG lSts;
  477. DWORD dwLen, dwType = 0;
  478. BOOL fDone = FALSE;
  479. if (ERROR_SUCCESS != m_lSts)
  480. throw (DWORD)m_lSts;
  481. while (!fDone)
  482. {
  483. dwLen = bfValue.Space();
  484. lSts = RegQueryValueEx(
  485. m_hKey,
  486. szKeyValue,
  487. NULL,
  488. &dwType,
  489. bfValue.Access(),
  490. &dwLen);
  491. switch (lSts)
  492. {
  493. case ERROR_SUCCESS:
  494. bfValue.Resize(dwLen, TRUE);
  495. fDone = TRUE;
  496. break;
  497. case ERROR_MORE_DATA:
  498. bfValue.Presize(dwLen);
  499. break;
  500. default:
  501. throw (DWORD)lSts;
  502. }
  503. }
  504. if (NULL != pdwType)
  505. *pdwType = dwType;
  506. }
  507. void
  508. CRegistry::GetValue(
  509. LPCTSTR szKeyValue,
  510. LPTSTR *pszValue,
  511. LPDWORD pdwType)
  512. {
  513. DWORD dwLen, dwType;
  514. TCHAR chTmp;
  515. CBuffer bfUnexpanded;
  516. LONG lSts;
  517. dwLen = 0;
  518. lSts = RegQueryValueEx(
  519. m_hKey,
  520. szKeyValue,
  521. NULL,
  522. &dwType,
  523. NULL,
  524. &dwLen);
  525. if (ERROR_SUCCESS != lSts)
  526. throw (DWORD)lSts;
  527. switch (dwType)
  528. {
  529. case REG_EXPAND_SZ:
  530. bfUnexpanded.Presize(dwLen);
  531. GetValue(szKeyValue, bfUnexpanded, &dwType);
  532. dwLen = ExpandEnvironmentStrings(
  533. (LPTSTR)bfUnexpanded.Access(),
  534. &chTmp,
  535. 0);
  536. if (0 == dwLen)
  537. throw GetLastError();
  538. dwLen = ExpandEnvironmentStrings(
  539. (LPTSTR)bfUnexpanded.Access(),
  540. (LPTSTR)m_bfResult.Resize(dwLen),
  541. dwLen);
  542. if (0 == dwLen)
  543. throw GetLastError();
  544. break;
  545. case REG_BINARY:
  546. case REG_MULTI_SZ:
  547. case REG_SZ:
  548. m_bfResult.Presize(dwLen);
  549. GetValue(szKeyValue, m_bfResult, &dwType);
  550. break;
  551. default:
  552. throw (DWORD)ERROR_BAD_FORMAT;
  553. }
  554. *pszValue = (LPTSTR)m_bfResult.Access();
  555. if (NULL != pdwType)
  556. *pdwType = dwType;
  557. }
  558. void
  559. CRegistry::GetValue(
  560. LPCTSTR szKeyValue,
  561. LPDWORD pdwValue,
  562. LPDWORD pdwType)
  563. const
  564. {
  565. LONG lSts;
  566. DWORD dwLen, dwType;
  567. CBuffer szExpanded;
  568. if (ERROR_SUCCESS != m_lSts)
  569. throw (DWORD)m_lSts;
  570. dwLen = sizeof(DWORD);
  571. lSts = RegQueryValueEx(
  572. m_hKey,
  573. szKeyValue,
  574. NULL,
  575. &dwType,
  576. (LPBYTE)pdwValue,
  577. &dwLen);
  578. if (ERROR_SUCCESS != lSts)
  579. throw (DWORD)lSts;
  580. switch (dwType)
  581. {
  582. case REG_DWORD_BIG_ENDIAN:
  583. *pdwValue = NTOHL(*pdwValue);
  584. break;
  585. case REG_DWORD:
  586. // case REG_DWORD_LITTLE_ENDIAN:
  587. break;
  588. default:
  589. throw (DWORD)ERROR_BAD_FORMAT;
  590. }
  591. if (NULL != pdwType)
  592. *pdwType = dwType;
  593. }
  594. void
  595. CRegistry::GetValue(
  596. LPCTSTR szKeyValue,
  597. LPBYTE *ppbValue,
  598. LPDWORD pcbLength,
  599. LPDWORD pdwType)
  600. {
  601. DWORD dwType;
  602. GetValue(szKeyValue, m_bfResult, &dwType);
  603. *ppbValue = m_bfResult.Access();
  604. *pcbLength = m_bfResult.Length();
  605. if (NULL != pdwType)
  606. *pdwType = dwType;
  607. }
  608. /*++
  609. SetValue:
  610. These methods provide write access to the values of the Value entries.
  611. Arguments:
  612. szKeyValue supplies the name of the Value entry to set.
  613. szValue supplies the new value of the entry as a string.
  614. dwValue supplies the new value of the entry as a DWORD.
  615. pbValue supplies the new value of the entry as a Binary string.
  616. cbLength supplies the length of the entry when it's a binary string.
  617. dwType supplies the registry type value.
  618. Return Value:
  619. None
  620. Throws:
  621. Any error encountered.
  622. Author:
  623. Doug Barlow (dbarlow) 7/15/1996
  624. --*/
  625. void
  626. CRegistry::SetValue(
  627. LPCTSTR szKeyValue,
  628. LPCTSTR szValue,
  629. DWORD dwType)
  630. const
  631. {
  632. LONG lSts;
  633. if (ERROR_SUCCESS != m_lSts)
  634. throw (DWORD)m_lSts;
  635. lSts = RegSetValueEx(
  636. m_hKey,
  637. szKeyValue,
  638. 0,
  639. dwType,
  640. (LPBYTE)szValue,
  641. (lstrlen(szValue) + 1) * sizeof(TCHAR));
  642. if (ERROR_SUCCESS != lSts)
  643. throw (DWORD)lSts;
  644. }
  645. void
  646. CRegistry::SetValue(
  647. LPCTSTR szKeyValue,
  648. DWORD dwValue,
  649. DWORD dwType)
  650. const
  651. {
  652. LONG lSts;
  653. if (ERROR_SUCCESS != m_lSts)
  654. throw (DWORD)m_lSts;
  655. if (REG_DWORD_BIG_ENDIAN == dwType)
  656. dwValue = HTONL(dwValue);
  657. lSts = RegSetValueEx(
  658. m_hKey,
  659. szKeyValue,
  660. 0,
  661. dwType,
  662. (LPBYTE)&dwValue,
  663. sizeof(DWORD));
  664. if (ERROR_SUCCESS != lSts)
  665. throw (DWORD)lSts;
  666. }
  667. void
  668. CRegistry::SetValue(
  669. LPCTSTR szKeyValue,
  670. LPCBYTE pbValue,
  671. DWORD cbLength,
  672. DWORD dwType)
  673. const
  674. {
  675. LONG lSts;
  676. if (ERROR_SUCCESS != m_lSts)
  677. throw (DWORD)m_lSts;
  678. lSts = RegSetValueEx(
  679. m_hKey,
  680. szKeyValue,
  681. 0,
  682. dwType,
  683. pbValue,
  684. cbLength);
  685. if (ERROR_SUCCESS != lSts)
  686. throw (DWORD)lSts;
  687. }
  688. /*++
  689. GetStringValue:
  690. This is an alternate mechanism for obtaining a string value.
  691. Arguments:
  692. szKeyValue supplies the name of the Key Value to obtain.
  693. pdwType, if non-null, receives the type of registry entry.
  694. Return Value:
  695. The value of the registry entry as a string pointer.
  696. Throws:
  697. Any errors encountered.
  698. Author:
  699. Doug Barlow (dbarlow) 7/16/1996
  700. --*/
  701. LPCTSTR
  702. CRegistry::GetStringValue(
  703. LPCTSTR szKeyValue,
  704. LPDWORD pdwType)
  705. {
  706. LPTSTR szResult;
  707. GetValue(szKeyValue, &szResult, pdwType);
  708. return szResult;
  709. }
  710. /*++
  711. GetNumericValue:
  712. This is an alternate mechanism for obtaining a numeric value.
  713. Arguments:
  714. szKeyValue supplies the name of the Key Value to obtain.
  715. pdwType, if non-null, receives the type of registry entry.
  716. Return Value:
  717. The value of the registry entry as a DWORD.
  718. Throws:
  719. Any errors encountered.
  720. Author:
  721. Doug Barlow (dbarlow) 7/16/1996
  722. --*/
  723. DWORD
  724. CRegistry::GetNumericValue(
  725. LPCTSTR szKeyValue,
  726. LPDWORD pdwType)
  727. const
  728. {
  729. DWORD dwResult;
  730. GetValue(szKeyValue, &dwResult, pdwType);
  731. return dwResult;
  732. }
  733. /*++
  734. GetBinaryValue:
  735. This is an alternate mechanism for obtaining a binary value.
  736. Arguments:
  737. szKeyValue supplies the name of the Key Value to obtain.
  738. pdwType, if non-null, receives the type of registry entry.
  739. Return Value:
  740. The value of the registry entry as a binary pointer.
  741. Throws:
  742. Any errors encountered.
  743. Author:
  744. Doug Barlow (dbarlow) 7/16/1996
  745. --*/
  746. LPCBYTE
  747. CRegistry::GetBinaryValue(
  748. LPCTSTR szKeyValue,
  749. LPDWORD pcbLength,
  750. LPDWORD pdwType)
  751. {
  752. LPBYTE pbResult;
  753. DWORD cbLength;
  754. GetValue(szKeyValue, &pbResult, &cbLength, pdwType);
  755. if (NULL != pcbLength)
  756. *pcbLength = cbLength;
  757. return pbResult;
  758. }
  759. /*++
  760. GetValueLength:
  761. This routine is designed to work in conjunction with GetBinaryValue, but may
  762. have other uses as well. It returns the length of the internal storage
  763. area, in bytes. Note DWORDs are not stored internally, so this value will
  764. not represent the size of a DWORD following a GetNumericValue call.
  765. Arguments:
  766. none
  767. Return Value:
  768. The length of the internal storage buffer, in bytes.
  769. Throws:
  770. Any errors encountered.
  771. Author:
  772. Doug Barlow (dbarlow) 7/16/1996
  773. --*/
  774. DWORD
  775. CRegistry::GetValueLength(
  776. void)
  777. const
  778. {
  779. if (ERROR_SUCCESS != m_lSts)
  780. throw (DWORD)m_lSts;
  781. return m_bfResult.Length();
  782. }
  783. /*++
  784. ValueExists:
  785. This routine tests for the existance of a given value, and optionally
  786. returns its type and length.
  787. Arguments:
  788. none
  789. Return Value:
  790. A boolean indication as to whether or not the value exists.
  791. Throws:
  792. Any errors encountered.
  793. Author:
  794. Doug Barlow (dbarlow) 7/16/1996
  795. --*/
  796. BOOL
  797. CRegistry::ValueExists(
  798. LPCTSTR szKeyValue,
  799. LPDWORD pcbLength,
  800. LPDWORD pdwType)
  801. const
  802. {
  803. LONG lSts;
  804. DWORD dwLen, dwType;
  805. BOOL fResult = FALSE;
  806. if (ERROR_SUCCESS != m_lSts)
  807. throw (DWORD)m_lSts;
  808. dwLen = 0;
  809. lSts = RegQueryValueEx(
  810. m_hKey,
  811. szKeyValue,
  812. NULL,
  813. &dwType,
  814. NULL,
  815. &dwLen);
  816. if (ERROR_SUCCESS == lSts)
  817. {
  818. if (NULL != pcbLength)
  819. *pcbLength = dwLen;
  820. if (NULL != pdwType)
  821. *pdwType = dwType;
  822. fResult = TRUE;
  823. }
  824. return fResult;
  825. }
  826. /*++
  827. GetDisposition:
  828. This routine returns the disposition of creation.
  829. Arguments:
  830. none
  831. Return Value:
  832. The return disposition flag from creating the registry entry.
  833. Throws:
  834. Any errors encountered.
  835. Author:
  836. Doug Barlow (dbarlow) 7/16/1996
  837. --*/
  838. DWORD
  839. CRegistry::GetDisposition(
  840. void)
  841. const
  842. {
  843. if (ERROR_SUCCESS != m_lSts)
  844. throw (DWORD)m_lSts;
  845. return m_dwDisposition;
  846. }
  847. /*++
  848. SetMultiStringValue:
  849. This method simplifies the work of adding a MultiString value to the
  850. registry.
  851. Arguments:
  852. szKeyValue supplies the name of the Value entry to set.
  853. mszValue supplies the new value of the entry as a multi-string.
  854. dwType supplies the registry type value.
  855. Return Value:
  856. None
  857. Throws:
  858. Any errors encountered as a DWORD status value.
  859. Author:
  860. Doug Barlow (dbarlow) 11/6/1996
  861. --*/
  862. void
  863. CRegistry::SetMultiStringValue(
  864. LPCTSTR szKeyValue,
  865. LPCTSTR mszValue,
  866. DWORD dwType)
  867. const
  868. {
  869. LONG lSts;
  870. if (ERROR_SUCCESS != m_lSts)
  871. throw (DWORD)m_lSts;
  872. lSts = RegSetValueEx(
  873. m_hKey,
  874. szKeyValue,
  875. 0,
  876. dwType,
  877. (LPBYTE)mszValue,
  878. MStrLen(mszValue) * sizeof(TCHAR));
  879. if (ERROR_SUCCESS != lSts)
  880. throw (DWORD)lSts;
  881. }
  882. /*++
  883. GetMultiStringValue:
  884. This method obtains a multi-string value from the registry.
  885. Arguments:
  886. szKeyValue supplies the name of the Key Value to obtain.
  887. pdwType, if non-null, receives the type of registry entry.
  888. Return Value:
  889. The registry value, as a multi-string.
  890. Throws:
  891. Any errors encountered as a DWORD status value.
  892. Author:
  893. Doug Barlow (dbarlow) 11/6/1996
  894. --*/
  895. LPCTSTR
  896. CRegistry::GetMultiStringValue(
  897. LPCTSTR szKeyValue,
  898. LPDWORD pdwType)
  899. {
  900. LPTSTR szResult;
  901. GetValue(szKeyValue, &szResult, pdwType);
  902. return szResult;
  903. }
  904. /*++
  905. SetAcls:
  906. This method sets security attributes for a single key, or an entire key
  907. branch.
  908. Arguments:
  909. SecurityInformation supplies the SECURITY_INFORMATION value (see
  910. RegSetKeySecurity in the SDK documentation).
  911. pSecurityDescriptor supplies the SECURITY_DESCRIPTOR value (see
  912. RegSetKeySecurity in the SDK documentation).
  913. fRecurse supplies an indicator as to whether to just set the ACL on this
  914. key (FALSE), or this key and all subkeys (TRUE).
  915. Return Value:
  916. None
  917. Throws:
  918. Errors are thrown as DWORD status codes.
  919. Author:
  920. Doug Barlow (dbarlow) 11/10/1998
  921. --*/
  922. void
  923. CRegistry::SetAcls(
  924. IN SECURITY_INFORMATION SecurityInformation,
  925. IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
  926. IN BOOL fRecurse)
  927. {
  928. LONG lSts;
  929. if (ERROR_SUCCESS != m_lSts)
  930. throw (DWORD)m_lSts;
  931. lSts = RegSetKeySecurity(
  932. m_hKey,
  933. SecurityInformation,
  934. pSecurityDescriptor);
  935. if (ERROR_SUCCESS != lSts)
  936. throw (DWORD)lSts;
  937. if (fRecurse)
  938. {
  939. CRegistry regSub;
  940. LPCTSTR szSubKey;
  941. DWORD dwIndex;
  942. for (dwIndex = 0;
  943. NULL != (szSubKey = Subkey(dwIndex));
  944. dwIndex += 1)
  945. {
  946. regSub.Open(m_hKey, szSubKey);
  947. regSub.SetAcls(
  948. SecurityInformation,
  949. pSecurityDescriptor);
  950. regSub.Close();
  951. }
  952. }
  953. }