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.

1210 lines
34 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1997.
  5. //
  6. // File: N C R E G . C P P
  7. //
  8. // Contents: Common routines for dealing with the registry.
  9. //
  10. // Notes:
  11. //
  12. // Author: danielwe 24 Mar 1997
  13. //
  14. //----------------------------------------------------------------------------
  15. #include <pch.h>
  16. #pragma hdrstop
  17. #include "ncdebug.h"
  18. #include "ncreg.h"
  19. #include "ncstring.h"
  20. //#include "ncperms.h"
  21. extern const TCHAR c_szBackslash[];
  22. extern const TCHAR c_szParameters[];
  23. extern const TCHAR c_szRegKeyServices[];
  24. //+---------------------------------------------------------------------------
  25. //
  26. // Function: HrRegAddStringToMultiSz
  27. //
  28. // Purpose: Add a string into a REG_MULTI_SZ registry value
  29. //
  30. // Arguments:
  31. // pszAddString [in] The string to add to the multi-sz
  32. // hkeyRoot [in] An open registry key, or one of the
  33. // predefined hkey values (HKEY_LOCAL_MACHINE,
  34. // for instance)
  35. // pszKeySubPath [in] Name of the subkey to open.
  36. // pszValueName [in] Name of the registry value that we're going to
  37. // modify.
  38. // dwFlags [in] Can contain one or more of the following
  39. // values:
  40. //
  41. // STRING_FLAG_ALLOW_DUPLICATES
  42. // Don't remove duplicate values when adding
  43. // the string to the list. Default is to
  44. // remove all other instance of this string.
  45. // STRING_FLAG_ENSURE_AT_FRONT
  46. // Ensure the string is the first element of
  47. // the list. If the string is present and
  48. // duplicates aren't allowed, move the
  49. // string to the end.
  50. // STRING_FLAG_ENSURE_AT_END
  51. // Ensure the string is the last
  52. // element of the list. This can not be used
  53. // with STRING_FLAG_ENSURE_AT_FRONT. If the
  54. // string is present and duplicates aren't
  55. // allowed, move the string to the end.
  56. // STRING_FLAG_ENSURE_AT_INDEX
  57. // Ensure that the string is at dwStringIndex
  58. // in the multi-sz. If the index specified
  59. // is greater than the number of strings
  60. // in the multi-sz, the string will be
  61. // placed at the end.
  62. // STRING_FLAG_DONT_MODIFY_IF_PRESENT
  63. // If the string already exists in the
  64. // multi-sz then no modication will take
  65. // place. Note: This takes precedent
  66. // over the presence/non-presence of the
  67. // STRING_FLAG_ALLOW_DUPLICATES flag.
  68. // i.e nothing will be added or removed
  69. // if this flag is set and the string was
  70. // present in the multi-sz
  71. // dwIndex [in] If STRING_FLAG_ENSURE_AT_INDEX is specified,
  72. // this is the index for the string position.
  73. // Otherwise, this value is ignored.
  74. //
  75. // Returns: S_OK or an HRESULT_FROM_WIN32 error code.
  76. //
  77. // Author: jeffspr 27 Mar 1997
  78. //
  79. HRESULT
  80. HrRegAddStringToMultiSz (
  81. IN PCTSTR pszAddString,
  82. IN HKEY hkeyRoot,
  83. IN PCTSTR pszKeySubPath,
  84. IN PCTSTR pszValueName,
  85. IN DWORD dwFlags,
  86. IN DWORD dwIndex)
  87. {
  88. HRESULT hr = S_OK;
  89. DWORD dwRegType = 0; // Should be REG_MULTI_SZ
  90. HKEY hkeyOpen = NULL; // Return value from RegCreateKeyEx
  91. HKEY hkeyUse = NULL; // The key value that we'll actually use
  92. LPBYTE pbOrderOld = NULL; // Return buffer for order reg value
  93. LPBYTE pbOrderNew = NULL; // Build buffer for order swap
  94. // Check for valid parameters
  95. if (!pszAddString || !hkeyRoot || !pszValueName)
  96. {
  97. Assert(pszAddString);
  98. Assert(hkeyRoot);
  99. Assert(pszValueName);
  100. hr = E_INVALIDARG;
  101. goto Exit;
  102. }
  103. // Check to make sure that no "remove" flags are being used, and that
  104. // mutually exclusive flags aren't being used together
  105. //
  106. if ((dwFlags & STRING_FLAG_REMOVE_SINGLE) ||
  107. (dwFlags & STRING_FLAG_REMOVE_ALL) ||
  108. ((dwFlags & STRING_FLAG_ENSURE_AT_FRONT) &&
  109. (dwFlags & STRING_FLAG_ENSURE_AT_END)))
  110. {
  111. AssertSz(FALSE, "Invalid flags in HrRegAddStringToMultiSz");
  112. hr = E_INVALIDARG;
  113. goto Exit;
  114. }
  115. // If the user passed in a subkey string, then we should attempt to open
  116. // the subkey of the passed in root, else we'll just use the
  117. // pre-opened hkeyRoot
  118. //
  119. if (pszKeySubPath)
  120. {
  121. // Open the key, creating if necessary
  122. //
  123. hr = HrRegCreateKeyEx (
  124. hkeyRoot, // Base hive
  125. pszKeySubPath, // Our reg path
  126. 0, // dwOptions
  127. KEY_QUERY_VALUE | KEY_SET_VALUE, // samDesired
  128. NULL, // lpSecurityAttributes
  129. &hkeyOpen, // Our return hkey.
  130. NULL);
  131. if (FAILED(hr))
  132. {
  133. goto Exit;
  134. }
  135. hkeyUse = hkeyOpen;
  136. }
  137. else
  138. {
  139. // Use the passed in key for the Query.
  140. //
  141. hkeyUse = hkeyRoot;
  142. }
  143. // Retrieve the existing REG_MULTI_SZ
  144. //
  145. hr = HrRegQueryValueWithAlloc (
  146. hkeyUse,
  147. pszValueName,
  148. &dwRegType,
  149. &pbOrderOld,
  150. NULL);
  151. if (FAILED(hr))
  152. {
  153. if (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND))
  154. {
  155. // This is OK. It just means that the value was missing, and we
  156. // should continue on, and create the value ourselves.
  157. hr = S_OK;
  158. }
  159. else
  160. {
  161. // Since there's an error that we didn't expect, drop out,
  162. // returning this error to the caller.
  163. //
  164. goto Exit;
  165. }
  166. }
  167. else
  168. {
  169. // If we did retrieve a value, then check to make sure that we're
  170. // dealing with a MULTI_SZ
  171. //
  172. if (dwRegType != REG_MULTI_SZ)
  173. {
  174. hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATATYPE);
  175. goto Exit;
  176. }
  177. }
  178. BOOL fChanged;
  179. hr = HrAddSzToMultiSz (pszAddString, (PCTSTR)pbOrderOld,
  180. dwFlags, dwIndex, (PTSTR*)&pbOrderNew, &fChanged);
  181. if ((S_OK == hr) && fChanged)
  182. {
  183. DWORD cbNew = CbOfMultiSzAndTermSafe ((PTSTR)pbOrderNew);
  184. // Save our string back into the registry
  185. //
  186. hr = HrRegSetValueEx (
  187. hkeyUse,
  188. pszValueName,
  189. REG_MULTI_SZ,
  190. (const BYTE *)pbOrderNew,
  191. cbNew);
  192. }
  193. Exit:
  194. // Close the key, if opened
  195. //
  196. RegSafeCloseKey (hkeyOpen);
  197. // Clean up the registry buffers
  198. //
  199. MemFree (pbOrderOld);
  200. MemFree (pbOrderNew);
  201. TraceError ("HrRegAddStringToMultiSz", hr);
  202. return hr;
  203. }
  204. //+---------------------------------------------------------------------------
  205. //
  206. // Function: HrRegAddStringToSz
  207. //
  208. // Purpose: Add a string into a REG_MULTI_SZ registry value
  209. //
  210. // Arguments:
  211. // pszAddString [in] The string to add to the multi-sz
  212. // hkeyRoot [in] An open registry key, or one of the
  213. // predefined hkey values (HKEY_LOCAL_MACHINE,
  214. // for instance)
  215. // pszKeySubPath [in] Name of the subkey to open.
  216. // pszValueName [in] Name of the registry value that we're going to
  217. // modify.
  218. // chDelimiter [in] The character to be used to delimit the
  219. // values. Most multi-valued REG_SZ strings are
  220. // delimited with either ',' or ' '. This will
  221. // be used to delimit the value that we add,
  222. // as well.
  223. // dwFlags [in] Can contain one or more of the following
  224. // values:
  225. //
  226. // STRING_FLAG_ALLOW_DUPLICATES
  227. // Don't remove duplicate values when adding
  228. // the string to the list. Default is to
  229. // remove all other instance of this string.
  230. // STRING_FLAG_ENSURE_AT_FRONT
  231. // Insert the string as the first element of
  232. // the list.
  233. // STRING_FLAG_ENSURE_AT_END
  234. // Insert the string as the last
  235. // element of the list. This can not be used
  236. // with STRING_FLAG_ENSURE_AT_FRONT.
  237. // STRING_FLAG_ENSURE_AT_INDEX
  238. // Ensure that the string is at dwStringIndex
  239. // in the sz. If the index specified
  240. // is greater than the number of strings
  241. // in the sz, the string will be
  242. // placed at the end.
  243. // dwStringIndex [in] If STRING_FLAG_ENSURE_AT_INDEX is specified,
  244. // this is the index for the string position.
  245. // Otherwise, this value is ignored.
  246. //
  247. // Returns: S_OK or an HRESULT_FROM_WIN32 error code.
  248. //
  249. // Author: jeffspr 27 Mar 1997
  250. //
  251. //
  252. // Note:
  253. // Might want to allow for the removal of leading/trailing spaces
  254. //
  255. HRESULT
  256. HrRegAddStringToSz (
  257. IN PCTSTR pszAddString,
  258. IN HKEY hkeyRoot,
  259. IN PCTSTR pszKeySubPath,
  260. IN PCTSTR pszValueName,
  261. IN TCHAR chDelimiter,
  262. IN DWORD dwFlags,
  263. IN DWORD dwStringIndex)
  264. {
  265. HRESULT hr = S_OK;
  266. DWORD dwRegType = 0; // Should be REG_MULTI_SZ
  267. HKEY hkeyOpen = NULL; // Open key to open
  268. PTSTR pszOrderOld = NULL; // Return buffer for order reg value
  269. PTSTR pszOrderNew = NULL; // Build buffer for order swap
  270. // Check for all of the required args
  271. //
  272. if (!pszAddString || !hkeyRoot || !pszValueName)
  273. {
  274. Assert(pszAddString);
  275. Assert(hkeyRoot);
  276. Assert(pszValueName);
  277. hr = E_INVALIDARG;
  278. goto Exit;
  279. }
  280. // Check to make sure that no "remove" flags are being used, and that
  281. // mutually exclusive flags aren't being used together
  282. //
  283. if ((dwFlags & STRING_FLAG_REMOVE_SINGLE) ||
  284. (dwFlags & STRING_FLAG_REMOVE_ALL))
  285. {
  286. AssertSz(FALSE, "Invalid flags in HrRegAddStringToSz");
  287. hr = E_INVALIDARG;
  288. goto Exit;
  289. }
  290. // Open the key, creating if necessary
  291. //
  292. hr = HrRegCreateKeyEx(
  293. hkeyRoot, // Base hive
  294. pszKeySubPath, // Our reg path
  295. 0, // dwOptions
  296. KEY_QUERY_VALUE | KEY_SET_VALUE, // samDesired
  297. NULL, // lpSecurityAttributes
  298. &hkeyOpen, // Our return hkey.
  299. NULL);
  300. if (FAILED(hr))
  301. {
  302. goto Exit;
  303. }
  304. // Retrieve the existing REG_SZ
  305. //
  306. hr = HrRegQueryValueWithAlloc(
  307. hkeyOpen,
  308. pszValueName,
  309. &dwRegType,
  310. (LPBYTE *) &pszOrderOld,
  311. NULL);
  312. if (FAILED(hr))
  313. {
  314. if (hr == HRESULT_FROM_WIN32 (ERROR_FILE_NOT_FOUND))
  315. {
  316. // This is OK. It just means that the value is missing. We
  317. // can handle this.
  318. hr = S_OK;
  319. }
  320. else
  321. {
  322. goto Exit;
  323. }
  324. }
  325. else
  326. {
  327. // If we did retrieve a value, then check to make sure that we're
  328. // dealing with a MULTI_SZ
  329. //
  330. if (dwRegType != REG_SZ)
  331. {
  332. hr = HRESULT_FROM_WIN32 (ERROR_INVALID_DATATYPE);
  333. goto Exit;
  334. }
  335. }
  336. hr = HrAddStringToDelimitedSz(pszAddString, pszOrderOld, chDelimiter,
  337. dwFlags, dwStringIndex, &pszOrderNew);
  338. if (S_OK == hr)
  339. {
  340. // Save our string back into the registry
  341. //
  342. hr = HrRegSetSz(hkeyOpen, pszValueName, pszOrderNew);
  343. if (FAILED(hr))
  344. {
  345. goto Exit;
  346. }
  347. }
  348. Exit:
  349. // Close the key, if open
  350. //
  351. RegSafeCloseKey (hkeyOpen);
  352. // Clean up the registry buffers
  353. //
  354. MemFree (pszOrderOld);
  355. MemFree (pszOrderNew);
  356. TraceError ("HrRegAddStringToSz", hr);
  357. return hr;
  358. }
  359. //+---------------------------------------------------------------------------
  360. //
  361. // Function: HrRegRemoveStringFromSz
  362. //
  363. // Purpose: Removes a string from a REG_SZ registry value
  364. //
  365. // Arguments:
  366. // pszRemoveString [in] The string to be removed from the multi-sz
  367. // hkeyRoot [in] An open registry key, or one of the
  368. // predefined hkey values (HKEY_LOCAL_MACHINE,
  369. // for instance)
  370. // pszKeySubPath [in] Name of the subkey to open.
  371. // pszValueName [in] Name of the registry value that we're going to
  372. // modify.
  373. // chDelimiter [in] The character to be used to delimit the
  374. // values. Most multi-valued REG_SZ strings are
  375. // delimited with either ',' or ' '.
  376. // dwFlags [in] Can contain one or more of the following
  377. // values:
  378. //
  379. // STRING_FLAG_REMOVE_SINGLE
  380. // Don't remove more than one value, if
  381. // multiple are present.
  382. // STRING_FLAG_REMOVE_ALL
  383. // If multiple matching values are present,
  384. // remove them all.
  385. //
  386. // Returns: S_OK or an HRESULT_FROM_WIN32 error code.
  387. //
  388. // Author: jeffspr 27 Mar 1997
  389. //
  390. //
  391. // Note:
  392. // Might want to allow for the removal of leading/trailing spaces
  393. //
  394. HRESULT
  395. HrRegRemoveStringFromSz (
  396. IN PCTSTR pszRemoveString,
  397. IN HKEY hkeyRoot,
  398. IN PCTSTR pszKeySubPath,
  399. IN PCTSTR pszValueName,
  400. IN TCHAR chDelimiter,
  401. IN DWORD dwFlags )
  402. {
  403. HRESULT hr = S_OK;
  404. DWORD dwRegType = 0; // Should be REG_MULTI_SZ
  405. HKEY hkeyOpen = NULL; // Open key to open
  406. PTSTR pszOrderOld = NULL; // Return buffer for order reg value
  407. PTSTR pszOrderNew = NULL; // Build buffer for order swap
  408. DWORD dwDataSize = 0;
  409. // Check for all of the required args
  410. //
  411. if (!pszRemoveString || !hkeyRoot || !pszValueName)
  412. {
  413. Assert(pszRemoveString);
  414. Assert(hkeyRoot);
  415. Assert(pszValueName);
  416. hr = E_INVALIDARG;
  417. goto Exit;
  418. }
  419. // Check to make sure that no "remove" flags are being used, and that
  420. // mutually exclusive flags aren't being used together
  421. //
  422. if ((dwFlags & STRING_FLAG_ENSURE_AT_FRONT) ||
  423. (dwFlags & STRING_FLAG_ENSURE_AT_END) ||
  424. ((dwFlags & STRING_FLAG_REMOVE_SINGLE) &&
  425. (dwFlags & STRING_FLAG_REMOVE_ALL)))
  426. {
  427. AssertSz(FALSE, "Invalid flags in HrRegAddStringToSz");
  428. hr = E_INVALIDARG;
  429. goto Exit;
  430. }
  431. // Open the key, creating if necessary
  432. //
  433. hr = HrRegOpenKeyEx (
  434. hkeyRoot, // Base hive
  435. pszKeySubPath, // Our reg path
  436. KEY_QUERY_VALUE | KEY_SET_VALUE, // samDesired
  437. &hkeyOpen); // Our return hkey
  438. if (FAILED(hr))
  439. {
  440. if (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND))
  441. {
  442. hr = S_OK;
  443. }
  444. goto Exit;
  445. }
  446. // Retrieve the existing REG_SZ
  447. //
  448. hr = HrRegQueryValueWithAlloc (
  449. hkeyOpen,
  450. pszValueName,
  451. &dwRegType,
  452. (LPBYTE *) &pszOrderOld,
  453. &dwDataSize);
  454. if (FAILED(hr))
  455. {
  456. if (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND))
  457. {
  458. // This is OK. It just means that the value is missing. We
  459. // can handle this.
  460. hr = S_OK;
  461. }
  462. goto Exit;
  463. }
  464. else
  465. {
  466. // If we did retrieve a value, then check to make sure that we're
  467. // dealing with a REG_SZ
  468. //
  469. if (dwRegType != REG_SZ)
  470. {
  471. hr = HRESULT_FROM_WIN32 (ERROR_INVALID_DATATYPE);
  472. goto Exit;
  473. }
  474. if (dwDataSize == 0)
  475. {
  476. // This is OK, but we're going to assert here anyway, because this is not
  477. // a case that I know about
  478. //
  479. AssertSz(dwDataSize > 0, "How did we retrieve something from the "
  480. "registry with 0 size?");
  481. hr = S_OK;
  482. goto Exit;
  483. }
  484. }
  485. hr = HrRemoveStringFromDelimitedSz (pszRemoveString, pszOrderOld,
  486. chDelimiter, dwFlags, &pszOrderNew);
  487. if (S_OK == hr)
  488. {
  489. // Save our string back into the registry
  490. //
  491. hr = HrRegSetSz (hkeyOpen, pszValueName, pszOrderNew);
  492. }
  493. Exit:
  494. // Close the key, if open
  495. //
  496. RegSafeCloseKey (hkeyOpen);
  497. // Clean up the registry buffers
  498. //
  499. MemFree (pszOrderOld);
  500. MemFree (pszOrderNew);
  501. TraceError("HrRegRemoveStringFromSz", hr);
  502. return hr;
  503. }
  504. //+---------------------------------------------------------------------------
  505. //
  506. // Function: HrRegRemoveStringFromMultiSz
  507. //
  508. // Purpose: Removes the specified string from a multi-sz, if it is present.
  509. //
  510. // Arguments:
  511. // pszRemoveString [in]
  512. // hkeyRoot [in]
  513. // pszKeySubPath [in]
  514. // pszValueName [in]
  515. // dwFlags [in] Can contain one or more of the following
  516. // values:
  517. //
  518. // STRING_FLAG_REMOVE_SINGLE
  519. // Don't remove more than one value, if
  520. // multiple are present.
  521. // [default] STRING_FLAG_REMOVE_ALL
  522. // If multiple matching values are present,
  523. // remove them all.
  524. //
  525. // Returns: S_OK or an HRESULT_FROM_WIN32 error code.
  526. //
  527. // Author: ScottBri 11-Apr-1997
  528. //
  529. // Notes:
  530. //
  531. HRESULT
  532. HrRegRemoveStringFromMultiSz (
  533. IN PCTSTR pszRemoveString,
  534. IN HKEY hkeyRoot,
  535. IN PCTSTR pszKeySubPath,
  536. IN PCTSTR pszValueName,
  537. IN DWORD dwFlags)
  538. {
  539. DWORD dwDataSize;
  540. DWORD dwRegType;
  541. HKEY hkey = NULL;
  542. HKEY hkeyUse = hkeyRoot;
  543. HRESULT hr;
  544. PTSTR psz = NULL;
  545. // Valid the input parameters
  546. if ((NULL == pszRemoveString) || (NULL == pszValueName) ||
  547. (NULL == hkeyRoot))
  548. {
  549. Assert(NULL != pszRemoveString);
  550. Assert(NULL != pszValueName);
  551. Assert(NULL != hkeyRoot);
  552. return E_INVALIDARG;
  553. }
  554. if ((STRING_FLAG_REMOVE_SINGLE & dwFlags) &&
  555. (STRING_FLAG_REMOVE_ALL & dwFlags))
  556. {
  557. AssertSz(FALSE, "Can't specify both 'remove all' and 'remove single'");
  558. return E_INVALIDARG;
  559. }
  560. if (NULL != pszKeySubPath)
  561. {
  562. hr = HrRegOpenKeyEx (hkeyRoot, pszKeySubPath, KEY_ALL_ACCESS, &hkey);
  563. if (S_OK != hr)
  564. {
  565. return hr;
  566. }
  567. hkeyUse = hkey;
  568. }
  569. // Retrieve the existing REG_SZ
  570. //
  571. hr = HrRegQueryValueWithAlloc (hkeyUse, pszValueName, &dwRegType,
  572. (LPBYTE *)&psz, &dwDataSize);
  573. if (FAILED(hr))
  574. {
  575. if (HRESULT_FROM_WIN32 (ERROR_FILE_NOT_FOUND) == hr)
  576. {
  577. // This is OK. It just means that the value is missing. We
  578. // can handle this.
  579. hr = S_OK;
  580. }
  581. goto Done;
  582. }
  583. else
  584. {
  585. // If we did retrieve a value, then check to make sure that we're
  586. // dealing with a MULTI_SZ
  587. //
  588. if (dwRegType != REG_MULTI_SZ)
  589. {
  590. hr = HRESULT_FROM_WIN32 (ERROR_INVALID_DATATYPE);
  591. goto Done;
  592. }
  593. }
  594. // Search for and extract the specified string if present
  595. Assert(psz);
  596. BOOL fRemoved;
  597. RemoveSzFromMultiSz (pszRemoveString, psz, dwFlags, &fRemoved);
  598. // Rewrite the registry value if it was changed
  599. if (fRemoved)
  600. {
  601. dwDataSize = CbOfMultiSzAndTermSafe (psz);
  602. hr = HrRegSetValueEx (hkeyUse, pszValueName, REG_MULTI_SZ,
  603. (const LPBYTE)psz, dwDataSize);
  604. }
  605. Done:
  606. RegSafeCloseKey (hkey);
  607. MemFree (psz);
  608. TraceError ("HrRegRemoveStringFromMultiSz", hr);
  609. return hr;
  610. }
  611. //+---------------------------------------------------------------------------
  612. //
  613. // Function: HrRegCreateKeyEx
  614. //
  615. // Purpose: Creates a registry key by calling RegCreateKeyEx.
  616. //
  617. // Arguments:
  618. // hkey [in]
  619. // pszSubkey [in]
  620. // dwOptions [in] See the Win32 documentation for the
  621. // samDesired [in] RegCreateKeyEx function.
  622. // lpSecurityAttributes [in]
  623. // phkResult [out]
  624. // pdwDisposition [out]
  625. //
  626. // Returns: S_OK or an HRESULT_FROM_WIN32 error code.
  627. //
  628. // Author: danielwe 25 Feb 1997
  629. //
  630. // Notes:
  631. //
  632. HRESULT
  633. HrRegCreateKeyEx (
  634. IN HKEY hkey,
  635. IN PCTSTR pszSubkey,
  636. IN DWORD dwOptions,
  637. IN REGSAM samDesired,
  638. IN LPSECURITY_ATTRIBUTES lpSecurityAttributes,
  639. OUT PHKEY phkResult,
  640. OUT LPDWORD pdwDisposition)
  641. {
  642. Assert (hkey);
  643. Assert (pszSubkey);
  644. Assert (phkResult);
  645. LONG lr = RegCreateKeyEx (hkey, pszSubkey, 0, NULL, dwOptions, samDesired,
  646. lpSecurityAttributes, phkResult, pdwDisposition);
  647. HRESULT hr = HRESULT_FROM_WIN32 (lr);
  648. if (FAILED(hr))
  649. {
  650. *phkResult = NULL;
  651. }
  652. TraceError("HrRegCreateKeyEx", hr);
  653. return hr;
  654. }
  655. //+---------------------------------------------------------------------------
  656. //
  657. // Function: HrRegDeleteKey
  658. //
  659. // Purpose: Delete the specified registry key.
  660. //
  661. // Arguments:
  662. // hkey [in] See the Win32 documentation for the RegDeleteKey.
  663. // pszSubkey [in] function.
  664. //
  665. // Returns: S_OK or an HRESULT_FROM_WIN32 error code.
  666. //
  667. // Author: shaunco 1 Apr 1997
  668. //
  669. // Notes:
  670. //
  671. HRESULT
  672. HrRegDeleteKey (
  673. IN HKEY hkey,
  674. IN PCTSTR pszSubkey)
  675. {
  676. Assert (hkey);
  677. Assert (pszSubkey);
  678. LONG lr = RegDeleteKey (hkey, pszSubkey);
  679. HRESULT hr = HRESULT_FROM_WIN32 (lr);
  680. TraceHr (ttidError, FAL, hr, ERROR_FILE_NOT_FOUND == lr,
  681. "HrRegDeleteKey");
  682. return hr;
  683. }
  684. //+---------------------------------------------------------------------------
  685. //
  686. // Function: HrRegDeleteKeyTree
  687. //
  688. // Purpose: Deletes an entire registry hive.
  689. //
  690. // Arguments:
  691. // hkeyParent [in] Handle to open key where the desired key resides.
  692. // pszRemoveKey [in] Name of key to delete.
  693. //
  694. // Returns: S_OK or an HRESULT_FROM_WIN32 error code.
  695. //
  696. // Author: danielwe 25 Feb 1997
  697. //
  698. // Notes:
  699. //
  700. HRESULT
  701. HrRegDeleteKeyTree (
  702. IN HKEY hkeyParent,
  703. IN PCTSTR pszRemoveKey)
  704. {
  705. Assert (hkeyParent);
  706. Assert (pszRemoveKey);
  707. // Open the key we want to remove
  708. HKEY hkeyRemove;
  709. HRESULT hr = HrRegOpenKeyEx(hkeyParent, pszRemoveKey, KEY_ALL_ACCESS,
  710. &hkeyRemove);
  711. if (S_OK == hr)
  712. {
  713. TCHAR szValueName [MAX_PATH];
  714. DWORD cchBuffSize = MAX_PATH;
  715. FILETIME ft;
  716. LONG lr;
  717. // Enum the keys children, and remove those sub-trees
  718. while (ERROR_SUCCESS == (lr = RegEnumKeyEx (hkeyRemove,
  719. 0,
  720. szValueName,
  721. &cchBuffSize,
  722. NULL,
  723. NULL,
  724. NULL,
  725. &ft)))
  726. {
  727. HrRegDeleteKeyTree (hkeyRemove, szValueName);
  728. cchBuffSize = MAX_PATH;
  729. }
  730. RegCloseKey (hkeyRemove);
  731. if ((ERROR_SUCCESS == lr) || (ERROR_NO_MORE_ITEMS == lr))
  732. {
  733. lr = RegDeleteKey (hkeyParent, pszRemoveKey);
  734. }
  735. hr = HRESULT_FROM_WIN32 (lr);
  736. }
  737. TraceHr (ttidError, FAL, hr,
  738. HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr,
  739. "HrRegDeleteKeyTree");
  740. return hr;
  741. }
  742. //+---------------------------------------------------------------------------
  743. //
  744. // Function: HrRegDeleteValue
  745. //
  746. // Purpose: Deletes the given registry value.
  747. //
  748. // Arguments:
  749. // hkey [in] See the Win32 documentation for the RegDeleteValue
  750. // pszValueName [in] function.
  751. //
  752. // Returns: S_OK or an HRESULT_FROM_WIN32 error code.
  753. //
  754. // Author: danielwe 25 Feb 1997
  755. //
  756. // Notes:
  757. //
  758. HRESULT
  759. HrRegDeleteValue (
  760. IN HKEY hkey,
  761. IN PCTSTR pszValueName)
  762. {
  763. Assert (hkey);
  764. Assert (pszValueName);
  765. LONG lr = RegDeleteValue (hkey, pszValueName);
  766. HRESULT hr = HRESULT_FROM_WIN32(lr);
  767. TraceErrorOptional("HrRegDeleteValue", hr, (ERROR_FILE_NOT_FOUND == lr));
  768. return hr;
  769. }
  770. //+---------------------------------------------------------------------------
  771. //
  772. // Function: HrRegEnumKeyEx
  773. //
  774. // Purpose: Enumerates subkeys of the specified open registry key.
  775. //
  776. // Arguments:
  777. // hkey [in]
  778. // dwIndex [in] See the Win32 documentation for the
  779. // pszSubkeyName [out] RegEnumKeyEx function.
  780. // pcchSubkeyName [inout]
  781. // pszClass [out]
  782. // pcchClass [inout]
  783. // pftLastWriteTime [out]
  784. //
  785. // Returns: S_OK or an HRESULT_FROM_WIN32 error code.
  786. //
  787. // Author: shaunco 30 Mar 1997
  788. //
  789. // Notes:
  790. //
  791. HRESULT
  792. HrRegEnumKeyEx (
  793. IN HKEY hkey,
  794. IN DWORD dwIndex,
  795. OUT PTSTR pszSubkeyName,
  796. IN OUT LPDWORD pcchSubkeyName,
  797. OUT PTSTR pszClass,
  798. IN OUT LPDWORD pcchClass,
  799. OUT FILETIME* pftLastWriteTime)
  800. {
  801. Assert (hkey);
  802. Assert (pszSubkeyName);
  803. Assert (pcchSubkeyName);
  804. Assert (pftLastWriteTime);
  805. LONG lr = RegEnumKeyEx (hkey, dwIndex, pszSubkeyName, pcchSubkeyName,
  806. NULL, pszClass, pcchClass, pftLastWriteTime);
  807. HRESULT hr = HRESULT_FROM_WIN32(lr);
  808. TraceHr (ttidError, FAL, hr, ERROR_NO_MORE_ITEMS == lr,
  809. "HrRegEnumKeyEx");
  810. return hr;
  811. }
  812. //+---------------------------------------------------------------------------
  813. //
  814. // Function: HrRegEnumValue
  815. //
  816. // Purpose: Enumerates the values for the specified open registry key.
  817. //
  818. // Arguments:
  819. // hkey [in]
  820. // dwIndex [in] See the Win32 documentation for the
  821. // pszValueName [out] RegEnumValue function.
  822. // pcbValueName [inout]
  823. // pdwType [out]
  824. // pbData [out]
  825. // pcbData [inout]
  826. //
  827. // Returns: S_OK or an HRESULT_FROM_WIN32 error code.
  828. //
  829. // Author: shaunco 30 Mar 1997
  830. //
  831. // Notes:
  832. //
  833. HRESULT
  834. HrRegEnumValue (
  835. IN HKEY hkey,
  836. IN DWORD dwIndex,
  837. OUT PTSTR pszValueName,
  838. IN OUT LPDWORD pcbValueName,
  839. OUT LPDWORD pdwType,
  840. OUT LPBYTE pbData,
  841. IN OUT LPDWORD pcbData)
  842. {
  843. Assert (hkey);
  844. Assert (pszValueName);
  845. Assert (pcbValueName);
  846. Assert (FImplies(pbData, pcbData));
  847. LONG lr = RegEnumValue (hkey, dwIndex, pszValueName, pcbValueName,
  848. NULL, pdwType, pbData, pcbData);
  849. HRESULT hr = HRESULT_FROM_WIN32 (lr);
  850. TraceErrorOptional("HrRegEnumValue", hr, (ERROR_NO_MORE_ITEMS == lr));
  851. return hr;
  852. }
  853. //+---------------------------------------------------------------------------
  854. //
  855. // Function: HrRegOpenKeyEx
  856. //
  857. // Purpose: Opens a registry key by calling RegOpenKeyEx.
  858. //
  859. // Arguments:
  860. // hkey [in]
  861. // pszSubkey [in] See the Win32 documentation for the
  862. // samDesired [in] RegOpenKeyEx function.
  863. // phkResult [out]
  864. //
  865. // Returns: S_OK or an HRESULT_FROM_WIN32 error code.
  866. //
  867. // Author: danielwe 25 Feb 1997
  868. //
  869. // Notes:
  870. //
  871. HRESULT
  872. HrRegOpenKeyEx (
  873. IN HKEY hkey,
  874. IN PCTSTR pszSubkey,
  875. IN REGSAM samDesired,
  876. OUT PHKEY phkResult)
  877. {
  878. Assert (hkey);
  879. Assert (pszSubkey);
  880. Assert (phkResult);
  881. LONG lr = RegOpenKeyEx (hkey, pszSubkey, 0, samDesired, phkResult);
  882. HRESULT hr = HRESULT_FROM_WIN32(lr);
  883. if (FAILED(hr))
  884. {
  885. *phkResult = NULL;
  886. }
  887. TraceErrorOptional("HrRegOpenKeyEx", hr, (ERROR_FILE_NOT_FOUND == lr));
  888. return hr;
  889. }
  890. //+---------------------------------------------------------------------------
  891. //
  892. // Function: HrRegOpenKeyEx
  893. //
  894. // Purpose: Opens a registry key by calling RegOpenKeyEx with the highest
  895. // access possible.
  896. //
  897. // Arguments:
  898. // hkey [in]
  899. // pszSubkey [in] See the Win32 documentation for the
  900. // phkResult [out]
  901. //
  902. // Returns: S_OK or an HRESULT_FROM_WIN32 error code.
  903. //
  904. // Author: scottbri 31-Oct-1997
  905. //
  906. // Notes:
  907. //
  908. HRESULT
  909. HrRegOpenKeyBestAccess (
  910. IN HKEY hkey,
  911. IN PCTSTR pszSubkey,
  912. OUT PHKEY phkResult)
  913. {
  914. Assert (hkey);
  915. Assert (pszSubkey);
  916. Assert (phkResult);
  917. LONG lr = RegOpenKeyEx (hkey, pszSubkey, 0, KEY_ALL_ACCESS, phkResult);
  918. HRESULT hr = HRESULT_FROM_WIN32 (lr);
  919. if (FAILED(hr) && (ERROR_FILE_NOT_FOUND != lr))
  920. {
  921. lr = RegOpenKeyEx (hkey, pszSubkey, 0, KEY_READ, phkResult);
  922. hr = HRESULT_FROM_WIN32 (lr);
  923. if (FAILED(hr))
  924. {
  925. *phkResult = NULL;
  926. }
  927. }
  928. TraceErrorOptional("HrRegOpenKeyEx", hr, (ERROR_FILE_NOT_FOUND == lr));
  929. return hr;
  930. }
  931. //+---------------------------------------------------------------------------
  932. //
  933. // Function: HrRegDuplicateKeyEx
  934. //
  935. // Purpose: Duplicates a registry key by calling RegOpenKeyEx.
  936. //
  937. // Arguments:
  938. // hkey [in]
  939. // samDesired [in] RegOpenKeyEx function.
  940. // phkResult [out]
  941. //
  942. // Returns: S_OK or an HRESULT_FROM_WIN32 error code.
  943. //
  944. // Author: mikemi 09 Apr 1997
  945. //
  946. // Notes:
  947. //
  948. HRESULT
  949. HrRegDuplicateKeyEx (
  950. IN HKEY hkey,
  951. IN REGSAM samDesired,
  952. OUT PHKEY phkResult)
  953. {
  954. Assert (hkey);
  955. Assert (phkResult);
  956. LONG lr = RegOpenKeyEx (hkey, NULL, 0, samDesired, phkResult);
  957. HRESULT hr = HRESULT_FROM_WIN32 (lr);
  958. if (FAILED(hr))
  959. {
  960. *phkResult = NULL;
  961. }
  962. TraceError("HrRegDuplicateKeyEx", hr);
  963. return hr;
  964. }
  965. HRESULT
  966. HrRegSetBool (
  967. IN HKEY hkey,
  968. IN PCTSTR pszValueName,
  969. IN BOOL fValue)
  970. {
  971. DWORD dwValue = !!fValue;
  972. return HrRegSetValueEx (hkey, pszValueName,
  973. REG_DWORD,
  974. (LPBYTE)&dwValue, sizeof(DWORD));
  975. }
  976. HRESULT
  977. HrRegSetDword (
  978. IN HKEY hkey,
  979. IN PCTSTR pszValueName,
  980. IN DWORD dwValue)
  981. {
  982. return HrRegSetValueEx (hkey, pszValueName,
  983. REG_DWORD,
  984. (LPBYTE)&dwValue, sizeof(DWORD));
  985. }
  986. //+---------------------------------------------------------------------------
  987. //
  988. // Function: HrRegSetValueEx
  989. //
  990. // Purpose: Sets the data for the given registry value by calling the
  991. // RegSetValueEx function.
  992. //
  993. // Arguments:
  994. // hkey [in]
  995. // pszValueName [in]
  996. // dwType [in] See the Win32 documentation for the RegSetValueEx
  997. // pbData [in] function.
  998. // cbData [in]
  999. //
  1000. // Returns: S_OK or an HRESULT_FROM_WIN32 error code.
  1001. //
  1002. // Author: danielwe 25 Feb 1997
  1003. //
  1004. // Notes:
  1005. //
  1006. HRESULT
  1007. HrRegSetValueEx (
  1008. IN HKEY hkey,
  1009. IN PCTSTR pszValueName,
  1010. IN DWORD dwType,
  1011. IN const BYTE *pbData,
  1012. IN DWORD cbData)
  1013. {
  1014. Assert (hkey);
  1015. Assert (FImplies (cbData > 0, pbData));
  1016. LONG lr = RegSetValueEx(hkey, pszValueName, 0, dwType, pbData, cbData);
  1017. HRESULT hr = HRESULT_FROM_WIN32 (lr);
  1018. TraceError("HrRegSetValue", hr);
  1019. return hr;
  1020. }
  1021. //+---------------------------------------------------------------------------
  1022. //
  1023. // Function: RegSafeCloseKey
  1024. //
  1025. // Purpose: Closes the given registry key if it is non-NULL.
  1026. //
  1027. // Arguments:
  1028. // hkey [in] Key to be closed. Can be NULL.
  1029. //
  1030. // Returns: Nothing.
  1031. //
  1032. // Author: danielwe 25 Feb 1997
  1033. //
  1034. // Notes: If hkey is NULL this function does nothing.
  1035. //
  1036. VOID
  1037. RegSafeCloseKey (
  1038. IN HKEY hkey)
  1039. {
  1040. if (hkey)
  1041. {
  1042. RegCloseKey(hkey);
  1043. }
  1044. }
  1045. //+---------------------------------------------------------------------------
  1046. //
  1047. // Function: HrRegRestoreKey
  1048. //
  1049. // Purpose: Wrapper for RegRestoreKey
  1050. //
  1051. // Arguments:
  1052. // hkey [in] Parent key to restore into
  1053. // pszFileName [in] Name of file containing registry info
  1054. // dwFlags [in] Flags for restore
  1055. //
  1056. // Returns: Win32 HRESULT if failure, otherwise S_OK
  1057. //
  1058. // Author: danielwe 8 Aug 1997
  1059. //
  1060. // Notes: See docs for RegRestoreKey for more info
  1061. //
  1062. HRESULT
  1063. HrRegRestoreKey (
  1064. IN HKEY hkey,
  1065. IN PCTSTR pszFileName,
  1066. IN DWORD dwFlags)
  1067. {
  1068. HRESULT hr = S_OK;
  1069. LONG lres;
  1070. Assert(hkey);
  1071. Assert(pszFileName);
  1072. lres = RegRestoreKey(hkey, pszFileName, dwFlags);
  1073. hr = HRESULT_FROM_WIN32(lres);
  1074. TraceError("HrRegRestoreKey", hr);
  1075. return hr;
  1076. }
  1077. //+---------------------------------------------------------------------------
  1078. //
  1079. // Function: HrRegSaveKey
  1080. //
  1081. // Purpose: Wrapper for RegSaveKey
  1082. //
  1083. // Arguments:
  1084. // hkey [in] Parent key to restore into
  1085. // pszFileName [in] Name of file containing registry info
  1086. // psa [in] Security attributes for the file
  1087. //
  1088. // Returns: Win32 HRESULT if failure, otherwise S_OK
  1089. //
  1090. // Author: BillBe 2 Jan 1998
  1091. //
  1092. // Notes: See docs for RegSaveKey for more info
  1093. //
  1094. HRESULT
  1095. HrRegSaveKey (
  1096. IN HKEY hkey,
  1097. IN PCTSTR pszFileName,
  1098. IN LPSECURITY_ATTRIBUTES psa)
  1099. {
  1100. HRESULT hr;
  1101. LONG lres;
  1102. Assert(hkey);
  1103. Assert(pszFileName);
  1104. lres = RegSaveKey (hkey, pszFileName, psa);
  1105. hr = HRESULT_FROM_WIN32(lres);
  1106. TraceError("HrRegSaveKey", hr);
  1107. return hr;
  1108. }