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.

1397 lines
28 KiB

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