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.

1385 lines
28 KiB

  1. /*++
  2. Copyright (c) Microsoft Corporation. All rights reserved.
  3. Module Name:
  4. Registry.cpp
  5. Abstract:
  6. Implementation of the registry wrapper class.
  7. Notes:
  8. ANSI & Unicode via TCHAR - runs on Win9x/NT/2K/XP etc.
  9. History:
  10. 01/29/2001 rparsons Created
  11. 03/02/2001 rparsons Major overhaul
  12. 12/16/2001 rparsons Cleanup
  13. 01/27/2002 rparsons Converted to TCHAR
  14. --*/
  15. #include "registry.h"
  16. /*++
  17. Routine Description:
  18. Allocates memory from the heap.
  19. Arguments:
  20. cbBytes - Count of bytes to allocate.
  21. Return Value:
  22. On success, a pointer to a block of memory.
  23. On failure, NULL.
  24. --*/
  25. LPVOID
  26. CRegistry::Malloc(
  27. IN SIZE_T cbBytes
  28. )
  29. {
  30. LPVOID pvReturn = NULL;
  31. pvReturn = HeapAlloc(GetProcessHeap(),
  32. HEAP_ZERO_MEMORY,
  33. cbBytes);
  34. return pvReturn;
  35. }
  36. /*++
  37. Routine Description:
  38. Frees memory from the heap.
  39. Arguments:
  40. lpMem - Pointer to a block of memory to free.
  41. Return Value:
  42. None.
  43. --*/
  44. void
  45. CRegistry::Free(
  46. IN LPVOID pvMem
  47. )
  48. {
  49. if (pvMem) {
  50. HeapFree(GetProcessHeap(), 0, pvMem);
  51. }
  52. }
  53. /*++
  54. Routine Description:
  55. Creates the specified key.
  56. Arguments:
  57. hKey - Handle to a predefined key.
  58. pszSubKey - Path to the sub key to create.
  59. samDesired - The desired access rights.
  60. Return Value:
  61. A handle to the key on success, NULL otherwise.
  62. --*/
  63. HKEY
  64. CRegistry::CreateKey(
  65. IN HKEY hKey,
  66. IN LPCTSTR pszSubKey,
  67. IN REGSAM samDesired
  68. )
  69. {
  70. HKEY hKeyLocal = NULL;
  71. DWORD dwDisposition;
  72. if (!hKey) {
  73. return NULL;
  74. }
  75. RegCreateKeyEx(hKey,
  76. pszSubKey,
  77. 0,
  78. NULL,
  79. REG_OPTION_NON_VOLATILE,
  80. samDesired,
  81. NULL,
  82. &hKeyLocal,
  83. &dwDisposition);
  84. return hKeyLocal;
  85. }
  86. /*++
  87. Routine Description:
  88. Creates the specified key.
  89. Arguments:
  90. hKey - Handle to a predefined key.
  91. pszSubKey - Path to the sub key to create.
  92. samDesired - The desired access rights.
  93. pdwDisposition - On return, the disposition.
  94. Return Value:
  95. A handle to the key on success, NULL otherwise.
  96. --*/
  97. HKEY
  98. CRegistry::CreateKey(
  99. IN HKEY hKey,
  100. IN LPCTSTR pszSubKey,
  101. IN REGSAM samDesired,
  102. OUT LPDWORD pdwDisposition
  103. )
  104. {
  105. HKEY hKeyLocal = NULL;
  106. if (!hKey || !pdwDisposition) {
  107. return NULL;
  108. }
  109. RegCreateKeyEx(hKey,
  110. pszSubKey,
  111. 0,
  112. NULL,
  113. REG_OPTION_NON_VOLATILE,
  114. samDesired,
  115. NULL,
  116. &hKeyLocal,
  117. pdwDisposition);
  118. return hKeyLocal;
  119. }
  120. /*++
  121. Routine Description:
  122. Opens the specified key.
  123. Arguments:
  124. hKey - Handle to a predefined key.
  125. pszSubKey - Path to the sub key to open.
  126. samDesired - The desired access rights.
  127. Return Value:
  128. A handle to the key on success, NULL otherwise.
  129. --*/
  130. HKEY
  131. CRegistry::OpenKey(
  132. IN HKEY hKey,
  133. IN LPCTSTR pszSubKey,
  134. IN REGSAM samDesired
  135. )
  136. {
  137. HKEY hReturnKey = NULL;
  138. if (!hKey || !samDesired) {
  139. return NULL;
  140. }
  141. RegOpenKeyEx(hKey,
  142. pszSubKey,
  143. 0,
  144. samDesired,
  145. &hReturnKey);
  146. return hReturnKey;
  147. }
  148. /*++
  149. Routine Description:
  150. Gets a size for a specified value name.
  151. Arguments:
  152. hKey - Open key handle (not predefined).
  153. pszValueName - Name of data value.
  154. lpType - Receives the type of data.
  155. Return Value:
  156. Number of bytes the value occupies.
  157. --*/
  158. DWORD
  159. CRegistry::GetStringSize(
  160. IN HKEY hKey,
  161. IN LPCTSTR pszValueName,
  162. OUT LPDWORD lpType OPTIONAL
  163. )
  164. {
  165. DWORD cbSize = 0;
  166. if (!hKey) {
  167. return 0;
  168. }
  169. RegQueryValueEx(hKey,
  170. pszValueName,
  171. 0,
  172. lpType,
  173. NULL,
  174. &cbSize);
  175. return cbSize;
  176. }
  177. /*++
  178. Routine Description:
  179. Closes the specified key.
  180. Arguments:
  181. hKey - Open key handle.
  182. Return Value:
  183. On success, ERROR_SUCCESS.
  184. --*/
  185. LONG
  186. CRegistry::CloseKey(
  187. IN HKEY hKey
  188. )
  189. {
  190. return RegCloseKey(hKey);
  191. }
  192. /*++
  193. Routine Description:
  194. Retrieves a string value from the registry.
  195. Arguments:
  196. hKey - Predefined or open key handle.
  197. pszSubKey - Path to the subkey.
  198. pszValueName - Name of data value.
  199. Return Value:
  200. The requested value data on success, NULL otherwise.
  201. --*/
  202. LPSTR
  203. CRegistry::GetString(
  204. IN HKEY hKey,
  205. IN LPCTSTR pszSubKey,
  206. IN LPCTSTR pszValueName
  207. )
  208. {
  209. DWORD cbSize;
  210. BOOL fResult = FALSE;
  211. LONG lResult;
  212. LPTSTR pszReturn = NULL;
  213. HKEY hLocalKey = NULL;
  214. if (!hKey) {
  215. return NULL;
  216. }
  217. __try {
  218. hLocalKey = hKey;
  219. if (IsPredefinedRegistryHandle(hKey)) {
  220. //
  221. // We'll need to open the key for them.
  222. //
  223. hLocalKey = this->OpenKey(hKey, pszSubKey, KEY_QUERY_VALUE);
  224. if (!hLocalKey) {
  225. __leave;
  226. }
  227. }
  228. //
  229. // Get the required string size and allocate
  230. // memory for the actual call.
  231. //
  232. cbSize = this->GetStringSize(hLocalKey, pszValueName, NULL);
  233. if (0 == cbSize) {
  234. __leave;
  235. }
  236. pszReturn = (LPTSTR)this->Malloc(cbSize * sizeof(TCHAR));
  237. if (!pszReturn) {
  238. __leave;
  239. }
  240. //
  241. // Make the actual call to get the data.
  242. //
  243. lResult = RegQueryValueEx(hLocalKey,
  244. pszValueName,
  245. 0,
  246. NULL,
  247. (LPBYTE)pszReturn,
  248. &cbSize);
  249. if (ERROR_SUCCESS != lResult) {
  250. __leave;
  251. }
  252. fResult = TRUE;
  253. } // try
  254. __finally {
  255. if (hLocalKey) {
  256. RegCloseKey(hLocalKey);
  257. }
  258. if (!fResult) {
  259. this->Free(pszReturn);
  260. }
  261. }
  262. return (fResult ? pszReturn : NULL);
  263. }
  264. /*++
  265. Routine Description:
  266. Retrieves a DWORD value from the registry.
  267. Arguments:
  268. hKey - Predefined or open key handle.
  269. pszSubKey - Path to the subkey.
  270. pszValueName - Name of data value.
  271. lpdwData - Pointer to store the value.
  272. Return Value:
  273. TRUE on success, FALSE otherwise.
  274. --*/
  275. BOOL
  276. CRegistry::GetDword(
  277. IN HKEY hKey,
  278. IN LPCTSTR pszSubKey,
  279. IN LPCTSTR pszValueName,
  280. IN OUT LPDWORD lpdwData
  281. )
  282. {
  283. DWORD cbSize;
  284. BOOL fResult = FALSE;
  285. LONG lResult;
  286. HKEY hLocalKey = NULL;
  287. if (!hKey || !lpdwData) {
  288. return FALSE;
  289. }
  290. __try {
  291. hLocalKey = hKey;
  292. if (IsPredefinedRegistryHandle(hKey)) {
  293. //
  294. // We'll need to open the key for them.
  295. //
  296. hLocalKey = this->OpenKey(hKey, pszSubKey, KEY_QUERY_VALUE);
  297. if (!hLocalKey) {
  298. __leave;
  299. }
  300. }
  301. //
  302. // Make the call to get the data.
  303. //
  304. cbSize = sizeof(DWORD);
  305. lResult = RegQueryValueEx(hLocalKey,
  306. pszValueName,
  307. 0,
  308. NULL,
  309. (LPBYTE)lpdwData,
  310. &cbSize);
  311. if (ERROR_SUCCESS != lResult) {
  312. __leave;
  313. }
  314. fResult = TRUE;
  315. } // try
  316. __finally {
  317. if (hLocalKey) {
  318. RegCloseKey(hLocalKey);
  319. }
  320. } //finally
  321. return fResult;
  322. }
  323. /*++
  324. Routine Description:
  325. Sets a DWORD value in the registry.
  326. Arguments:
  327. hKey - Predefined or open key handle.
  328. pszSubKey - Path to the subkey.
  329. pszValueName - Name of data value.
  330. dwData - Value to store.
  331. Return Value:
  332. TRUE on success, FALSE otherwise.
  333. --*/
  334. BOOL
  335. CRegistry::SetDword(
  336. IN HKEY hKey,
  337. IN LPCTSTR pszSubKey,
  338. IN LPCTSTR pszValueName,
  339. IN DWORD dwData
  340. )
  341. {
  342. LONG lResult;
  343. BOOL fResult = FALSE;
  344. HKEY hLocalKey = NULL;
  345. if (!hKey) {
  346. return FALSE;
  347. }
  348. __try {
  349. hLocalKey = hKey;
  350. if (IsPredefinedRegistryHandle(hKey)) {
  351. //
  352. // We'll need to open the key for them.
  353. //
  354. hLocalKey = this->OpenKey(hKey, pszSubKey, KEY_SET_VALUE);
  355. if (!hLocalKey) {
  356. __leave;
  357. }
  358. }
  359. //
  360. // Make the call to set the data.
  361. //
  362. lResult = RegSetValueEx(hLocalKey,
  363. pszValueName,
  364. 0,
  365. REG_DWORD,
  366. (const BYTE*)&dwData,
  367. sizeof(DWORD));
  368. if (ERROR_SUCCESS != lResult) {
  369. __leave;
  370. }
  371. fResult = TRUE;
  372. } // try
  373. __finally {
  374. if (hLocalKey) {
  375. RegCloseKey(hLocalKey);
  376. }
  377. } // finally
  378. return fResult;
  379. }
  380. /*++
  381. Routine Description:
  382. Sets a string value in the registry.
  383. Arguments:
  384. hKey - Predefined or open key handle.
  385. pszSubKey - Path to the subkey.
  386. pszValueName - Name of data value.
  387. pszData - Value to store.
  388. Return Value:
  389. TRUE on success, FALSE otherwise.
  390. --*/
  391. BOOL
  392. CRegistry::SetString(
  393. IN HKEY hKey,
  394. IN LPCTSTR pszSubKey,
  395. IN LPCTSTR pszValueName,
  396. IN LPCTSTR pszData
  397. )
  398. {
  399. HKEY hLocalKey = NULL;
  400. BOOL fResult = FALSE;
  401. LONG lResult;
  402. if (!hKey) {
  403. return FALSE;
  404. }
  405. __try {
  406. hLocalKey = hKey;
  407. if (IsPredefinedRegistryHandle(hKey)) {
  408. //
  409. // We'll need to open the key for them.
  410. //
  411. hLocalKey = this->OpenKey(hKey, pszSubKey, KEY_SET_VALUE);
  412. if (!hLocalKey) {
  413. __leave;
  414. }
  415. }
  416. lResult = RegSetValueEx(hLocalKey,
  417. pszValueName,
  418. 0,
  419. REG_SZ,
  420. (const BYTE*)pszData,
  421. _tcslen(pszData) + 1);
  422. if (ERROR_SUCCESS != lResult) {
  423. __leave;
  424. }
  425. fResult = TRUE;
  426. } // try
  427. __finally {
  428. if (hLocalKey) {
  429. RegCloseKey(hLocalKey);
  430. }
  431. } // finally
  432. return fResult;
  433. }
  434. /*++
  435. Routine Description:
  436. Sets a MULTI_SZ string value in the registry.
  437. Arguments:
  438. hKey - Predefined or open key handle.
  439. pszSubKey - Path to the subkey.
  440. pszValueName - Name of data value.
  441. pszData - Value to store.
  442. cbSize - Size of the data to store.
  443. Return Value:
  444. TRUE on success, FALSE otherwise.
  445. --*/
  446. BOOL
  447. CRegistry::SetMultiSzString(
  448. IN HKEY hKey,
  449. IN LPCTSTR pszSubKey,
  450. IN LPCTSTR pszValueName,
  451. IN LPCTSTR pszData,
  452. IN DWORD cbSize
  453. )
  454. {
  455. HKEY hLocalKey = NULL;
  456. BOOL fResult = FALSE;
  457. LONG lResult;
  458. if (!hKey) {
  459. return FALSE;
  460. }
  461. __try {
  462. hLocalKey = hKey;
  463. if (IsPredefinedRegistryHandle(hKey)) {
  464. //
  465. // We'll need to open the key for them.
  466. //
  467. hLocalKey = this->OpenKey(hKey, pszSubKey, KEY_SET_VALUE);
  468. if (!hLocalKey) {
  469. __leave;
  470. }
  471. }
  472. lResult = RegSetValueEx(hLocalKey,
  473. pszValueName,
  474. 0,
  475. REG_MULTI_SZ,
  476. (const BYTE*)pszData,
  477. cbSize);
  478. if (ERROR_SUCCESS != lResult) {
  479. __leave;
  480. }
  481. fResult = TRUE;
  482. } // try
  483. __finally {
  484. if (hLocalKey) {
  485. RegCloseKey(hLocalKey);
  486. }
  487. } // finally
  488. return fResult;
  489. }
  490. /*++
  491. Routine Description:
  492. Deletes the specified value from the registry.
  493. Arguments:
  494. hKey - Handle to a predefined key.
  495. pszSubKey - Path to the subkey.
  496. pszValueName - Name of the value to delete.
  497. Return Value:
  498. TRUE on success, FALSE otherwise.
  499. --*/
  500. BOOL
  501. CRegistry::DeleteString(
  502. IN HKEY hKey,
  503. IN LPCTSTR pszSubKey,
  504. IN LPCTSTR pszValueName
  505. )
  506. {
  507. HKEY hLocalKey = NULL;
  508. BOOL fResult = FALSE;
  509. LONG lResult;
  510. if (!hKey) {
  511. return FALSE;
  512. }
  513. __try {
  514. hLocalKey = hKey;
  515. if (IsPredefinedRegistryHandle(hKey)) {
  516. //
  517. // We'll need to open the key for them.
  518. //
  519. hLocalKey = this->OpenKey(hKey, pszSubKey, KEY_SET_VALUE);
  520. if (NULL == hLocalKey) {
  521. __leave;
  522. }
  523. }
  524. //
  525. // Delete the value.
  526. //
  527. lResult = RegDeleteValue(hLocalKey, pszValueName);
  528. if (ERROR_SUCCESS != lResult) {
  529. __leave;
  530. }
  531. fResult = TRUE;
  532. } // try
  533. __finally {
  534. if (hLocalKey) {
  535. RegCloseKey(hLocalKey);
  536. }
  537. } // finally
  538. return fResult;
  539. }
  540. /*++
  541. Routine Description:
  542. Adds a string to a REG_MULTI_SZ key.
  543. Arguments:
  544. hKey - Predefined or open key handle.
  545. pszSubKey - Path to the subkey.
  546. pszEntry - Name of entry to add.
  547. Return Value:
  548. TRUE on success, FALSE otherwise.
  549. --*/
  550. BOOL
  551. CRegistry::AddStringToMultiSz(
  552. IN HKEY hKey,
  553. IN LPCTSTR pszSubKey,
  554. IN LPCTSTR pszEntry
  555. )
  556. {
  557. int nLen = 0;
  558. HKEY hLocalKey = NULL;
  559. DWORD cbSize = 0, dwType = 0;
  560. LPTSTR pszNew = NULL, pszKey = NULL;
  561. BOOL fResult = FALSE;
  562. LONG lResult;
  563. if (!hKey || !pszEntry) {
  564. return FALSE;
  565. }
  566. __try {
  567. hLocalKey = hKey;
  568. if (IsPredefinedRegistryHandle(hKey)) {
  569. //
  570. // We'll need to open the key for them.
  571. //
  572. hLocalKey = this->OpenKey(hKey,
  573. pszSubKey,
  574. KEY_QUERY_VALUE | KEY_SET_VALUE);
  575. if (NULL == hLocalKey) {
  576. __leave;
  577. }
  578. }
  579. //
  580. // Get the required string size and allocate
  581. // memory for the actual call.
  582. //
  583. cbSize = this->GetStringSize(hLocalKey, pszEntry, &dwType);
  584. if (0 == cbSize || dwType != REG_MULTI_SZ) {
  585. __leave;
  586. }
  587. pszKey = (LPSTR)this->Malloc(cbSize * sizeof(TCHAR));
  588. if (!pszKey) {
  589. __leave;
  590. }
  591. //
  592. // Get the actual data.
  593. //
  594. lResult = RegQueryValueEx(hLocalKey,
  595. pszEntry,
  596. 0,
  597. 0,
  598. (LPBYTE)pszKey,
  599. &cbSize);
  600. if (ERROR_SUCCESS != lResult) {
  601. __leave;
  602. }
  603. pszNew = pszKey;
  604. while (*pszNew) {
  605. nLen = _tcslen(pszNew);
  606. //
  607. // Move to the next string.
  608. //
  609. pszNew += nLen + 1;
  610. //
  611. // At end of list of strings, append here.
  612. //
  613. if (!*pszNew) {
  614. StringCchCopy(pszNew, nLen, pszEntry);
  615. pszNew += _tcslen(pszEntry) + 1;
  616. *pszNew = 0;
  617. nLen = this->ListStoreLen(pszKey);
  618. lResult = RegSetValueEx(hKey,
  619. pszEntry,
  620. 0,
  621. REG_MULTI_SZ,
  622. (const BYTE*)pszKey,
  623. nLen);
  624. if (lResult != ERROR_SUCCESS) {
  625. __leave;
  626. } else {
  627. fResult = TRUE;
  628. }
  629. break;
  630. }
  631. }
  632. } // try
  633. __finally {
  634. if (pszKey) {
  635. this->Free(pszKey);
  636. }
  637. if (hLocalKey) {
  638. RegCloseKey(hKey);
  639. }
  640. } // finally
  641. return fResult;
  642. }
  643. /*++
  644. Routine Description:
  645. Removes a string from a REG_MULTI_SZ key.
  646. Arguments:
  647. hKey - Predefined or open key handle.
  648. pszSubKey - Path to the subkey.
  649. pszEntry - Name of entry to remove.
  650. Return Value:
  651. TRUE on success, FALSE otherwise.
  652. --*/
  653. BOOL
  654. CRegistry::RemoveStringFromMultiSz(
  655. IN HKEY hKey,
  656. IN LPCTSTR pszSubKey,
  657. IN LPCTSTR pszEntry
  658. )
  659. {
  660. LPBYTE lpBuf = NULL;
  661. HKEY hLocalKey = NULL;
  662. TCHAR* pszFirst = NULL;
  663. TCHAR* pszSecond = NULL;
  664. DWORD dwType = 0, cbSize = 0;
  665. DWORD dwNameLen = 0, dwNameOffset = 0, dwSize = 0;
  666. BOOL fResult = FALSE;
  667. LONG lResult;
  668. if (!hKey || !pszEntry) {
  669. return FALSE;
  670. }
  671. __try {
  672. hLocalKey = hKey;
  673. if (IsPredefinedRegistryHandle(hKey)) {
  674. //
  675. // We'll need to open the key for them.
  676. //
  677. hLocalKey = this->OpenKey(hKey,
  678. pszSubKey,
  679. KEY_QUERY_VALUE | KEY_SET_VALUE);
  680. if (!hLocalKey) {
  681. __leave;
  682. }
  683. }
  684. //
  685. // Get the required string size and allocate
  686. // memory for the actual call.
  687. //
  688. cbSize = this->GetStringSize(hLocalKey, pszEntry, &dwType);
  689. if (0 == cbSize || dwType != REG_MULTI_SZ) {
  690. __leave;
  691. }
  692. lpBuf = (LPBYTE)this->Malloc(cbSize * sizeof(TCHAR));
  693. if (!lpBuf) {
  694. __leave;
  695. }
  696. //
  697. // Get the actual data.
  698. //
  699. lResult = RegQueryValueEx(hLocalKey,
  700. pszEntry,
  701. 0,
  702. 0,
  703. (LPBYTE)lpBuf,
  704. &cbSize);
  705. if (ERROR_SUCCESS != lResult) {
  706. __leave;
  707. }
  708. //
  709. // Attempt to find the string we're looking for.
  710. //
  711. for (pszFirst = (TCHAR*)lpBuf; *pszFirst; pszFirst += dwNameLen) {
  712. dwNameLen = _tcslen(pszFirst) + 1; // Length of name plus NULL
  713. dwNameOffset += dwNameLen;
  714. //
  715. // Check for a match.
  716. //
  717. if (!_tcsicmp(pszFirst, pszEntry)) {
  718. dwSize = _tcslen(pszFirst) + 1; // Length of name
  719. pszSecond = (TCHAR*)pszFirst + dwSize;
  720. while(*pszSecond)
  721. while(*pszSecond)
  722. *pszFirst++ = *pszSecond++;
  723. *pszFirst++ = *pszSecond++;
  724. *pszFirst = '\0';
  725. //
  726. // Found a match - update the key.
  727. //
  728. lResult = RegSetValueEx(hLocalKey,
  729. pszEntry,
  730. 0,
  731. REG_MULTI_SZ,
  732. (const BYTE*)lpBuf,
  733. cbSize - dwSize);
  734. if (lResult != ERROR_SUCCESS) {
  735. __leave;
  736. } else {
  737. fResult = TRUE;
  738. }
  739. break;
  740. }
  741. }
  742. } // try
  743. __finally {
  744. if (lpBuf) {
  745. this->Free(lpBuf);
  746. }
  747. if (hLocalKey) {
  748. RegCloseKey(hLocalKey);
  749. }
  750. } // finally
  751. return fResult;
  752. }
  753. /*++
  754. Routine Description:
  755. Determines if the specified subkey is present.
  756. Arguments:
  757. hKey - Predefined or open key handle.
  758. pszSubKey - Path to the subkey.
  759. Return Value:
  760. TRUE if it's present, FALSE otherwise.
  761. --*/
  762. BOOL
  763. CRegistry::IsRegistryKeyPresent(
  764. IN HKEY hKey,
  765. IN LPCTSTR pszSubKey
  766. )
  767. {
  768. BOOL fResult = FALSE;
  769. HKEY hLocalKey = NULL;
  770. if (!hKey || !pszSubKey) {
  771. return FALSE;
  772. }
  773. __try {
  774. hLocalKey = hKey;
  775. //
  776. // Check for the presence of the key.
  777. //
  778. hLocalKey = this->OpenKey(hKey, pszSubKey, KEY_QUERY_VALUE);
  779. if (NULL == hLocalKey) {
  780. __leave;
  781. } else {
  782. fResult = TRUE;
  783. }
  784. } // try
  785. __finally {
  786. if (hLocalKey) {
  787. RegCloseKey(hLocalKey);
  788. }
  789. } // finally
  790. return fResult;
  791. }
  792. /*++
  793. Routine Description:
  794. Restores the specified registry key.
  795. Arguments:
  796. hKey - Predefined or open key handle.
  797. pszSubKey - Path to the subkey.
  798. pszFileName - Path & name of the file to restore.
  799. fGrantPrivs - Flag to indicate if we should grant
  800. privileges to the user.
  801. Return Value:
  802. TRUE on success, FALSE otherwise.
  803. --*/
  804. BOOL
  805. CRegistry::RestoreKey(
  806. IN HKEY hKey,
  807. IN LPCTSTR pszSubKey,
  808. IN LPCTSTR pszFileName,
  809. IN BOOL fGrantPrivs
  810. )
  811. {
  812. BOOL fResult = FALSE;
  813. HKEY hLocalKey = NULL;
  814. LONG lResult;
  815. if (!hKey || !pszSubKey || !pszFileName) {
  816. return FALSE;
  817. }
  818. __try {
  819. //
  820. // If necessary, grant privileges for the restore
  821. //
  822. if (fGrantPrivs) {
  823. this->ModifyTokenPrivilege(_T("SeRestorePrivilege"), TRUE);
  824. }
  825. lResult = RegCreateKeyEx(hKey,
  826. pszSubKey,
  827. 0,
  828. NULL,
  829. 0,
  830. KEY_ALL_ACCESS,
  831. NULL,
  832. &hLocalKey,
  833. 0);
  834. if (ERROR_SUCCESS != lResult) {
  835. __leave;
  836. }
  837. //
  838. // Restore the key from the specified file.
  839. //
  840. lResult = RegRestoreKey(hLocalKey, pszFileName, REG_FORCE_RESTORE);
  841. if (ERROR_SUCCESS != lResult) {
  842. __leave;
  843. }
  844. RegFlushKey(hLocalKey);
  845. fResult = TRUE;
  846. } // try
  847. __finally {
  848. if (hLocalKey) {
  849. RegCloseKey(hLocalKey);
  850. }
  851. if (fGrantPrivs) {
  852. this->ModifyTokenPrivilege(_T("SeRestorePrivilege"), FALSE);
  853. }
  854. } // finally
  855. return fResult;
  856. }
  857. /*++
  858. Routine Description:
  859. Makes a backup of the specified registry key.
  860. Arguments:
  861. hKey - Predefined or open key handle.
  862. pszSubKey - Path to the subkey.
  863. pszFileName - Path & name of the file to restore.
  864. fGrantPrivs - Flag to indicate if we should grant
  865. privileges to the user.
  866. Return Value:
  867. TRUE on success, FALSE otherwise.
  868. --*/
  869. BOOL
  870. CRegistry::BackupRegistryKey(
  871. IN HKEY hKey,
  872. IN LPCTSTR pszSubKey,
  873. IN LPCTSTR pszFileName,
  874. IN BOOL fGrantPrivs
  875. )
  876. {
  877. BOOL fResult = FALSE;
  878. HKEY hLocalKey = NULL;
  879. DWORD dwDisposition;
  880. LONG lResult;
  881. if (!hKey || !pszSubKey || !pszFileName) {
  882. return FALSE;
  883. }
  884. __try {
  885. if (fGrantPrivs) {
  886. ModifyTokenPrivilege(_T("SeBackupPrivilege"), TRUE);
  887. }
  888. lResult = RegCreateKeyEx(hKey,
  889. pszSubKey,
  890. 0,
  891. NULL,
  892. REG_OPTION_BACKUP_RESTORE,
  893. KEY_QUERY_VALUE, // this argument is ignored
  894. NULL,
  895. &hLocalKey,
  896. &dwDisposition);
  897. if (ERROR_SUCCESS != lResult) {
  898. __leave;
  899. }
  900. //
  901. // Verify that we didn't create a new key.
  902. //
  903. if (REG_CREATED_NEW_KEY == dwDisposition) {
  904. __leave;
  905. }
  906. //
  907. // Save the key to the file.
  908. //
  909. lResult = RegSaveKey(hLocalKey, pszFileName, NULL);
  910. if (ERROR_SUCCESS != lResult) {
  911. __leave;
  912. } else {
  913. fResult = TRUE;
  914. }
  915. } // try
  916. __finally {
  917. if (hLocalKey) {
  918. RegCloseKey(hLocalKey);
  919. }
  920. if (fGrantPrivs) {
  921. this->ModifyTokenPrivilege(_T("SeBackupPrivilege"), FALSE);
  922. }
  923. } // finally
  924. return fResult;
  925. }
  926. /*++
  927. Routine Description:
  928. Helper function that calculates the size of MULTI_SZ string.
  929. Arguments:
  930. pszList - MULTI_SZ string.
  931. Return Value:
  932. Size of the string.
  933. --*/
  934. int
  935. CRegistry::ListStoreLen(
  936. IN LPTSTR pszList
  937. )
  938. {
  939. int nStoreLen = 2, nLen = 0;
  940. if (!pszList) {
  941. return 0;
  942. }
  943. while (*pszList) {
  944. nLen = _tcslen(pszList) + 1;
  945. nStoreLen += nLen * 2;
  946. pszList += nLen;
  947. }
  948. return nStoreLen;
  949. }
  950. /*++
  951. Routine Description:
  952. Enables or disables a specified privilege.
  953. Arguments:
  954. pszPrivilege - The name of the privilege.
  955. fEnable - A flag to indicate if the
  956. privilege should be enabled.
  957. Return Value:
  958. TRUE on success, FALSE otherwise.
  959. --*/
  960. BOOL
  961. CRegistry::ModifyTokenPrivilege(
  962. IN LPCTSTR pszPrivilege,
  963. IN BOOL fEnable
  964. )
  965. {
  966. HANDLE hToken = NULL;
  967. LUID luid;
  968. BOOL bResult = FALSE;
  969. BOOL bReturn;
  970. TOKEN_PRIVILEGES tp;
  971. if (!pszPrivilege) {
  972. return FALSE;
  973. }
  974. __try {
  975. //
  976. // Get a handle to the access token associated with the current process.
  977. //
  978. OpenProcessToken(GetCurrentProcess(),
  979. TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
  980. &hToken);
  981. if (!hToken) {
  982. __leave;
  983. }
  984. //
  985. // Obtain a LUID for the specified privilege.
  986. //
  987. if (!LookupPrivilegeValue(NULL, pszPrivilege, &luid)) {
  988. __leave;
  989. }
  990. tp.PrivilegeCount = 1;
  991. tp.Privileges[0].Luid = luid;
  992. tp.Privileges[0].Attributes = fEnable ? SE_PRIVILEGE_ENABLED : 0;
  993. //
  994. // Modify the access token.
  995. //
  996. bReturn = AdjustTokenPrivileges(hToken,
  997. FALSE,
  998. &tp,
  999. sizeof(TOKEN_PRIVILEGES),
  1000. NULL,
  1001. NULL);
  1002. if (!bReturn || GetLastError() == ERROR_NOT_ALL_ASSIGNED) {
  1003. __leave;
  1004. }
  1005. bResult = TRUE;
  1006. } // try
  1007. __finally {
  1008. if (hToken) {
  1009. CloseHandle(hToken);
  1010. }
  1011. } // finally
  1012. return bResult;
  1013. }