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.

912 lines
27 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Copyright (C) 1992, Microsoft Corporation.
  4. //
  5. // File: registry.cxx
  6. //
  7. // Contents: implementations for CRegKey member Members
  8. //
  9. // Members: CRegKey::CRegKey - constructor for registry key object
  10. // CRegKey::CRegKey - constructor for registry key object
  11. // CRegKey::CreateKey - real worker for constructors
  12. // CRegKey::~CRegKey - destructor for registry key object
  13. // CRegKey::Delete - delete a registry key
  14. // CRegKey::EnumValues - enumerate values of a registry key
  15. // CRegKey::EnumKeys - enumerate subkeys of a registry key
  16. // CRegKey::NotifyChange - setup change notification for a key
  17. //
  18. // CRegValue::GetValue - sets a registry value
  19. // CRegValue::SetValue - retrieves a registry value
  20. // CRegValue::Delete - deletes a registry value
  21. // CRegValue::GetTypeCode - returns the type code of the value
  22. //
  23. // CRegMSZ::SetStrings - sets a multi-string registry value
  24. // CRegMSZ::GetStrings - retrieves a multi-string registry value
  25. //
  26. // History: 09/30/92 Rickhi Created
  27. // 09/22/93 AlokS Took out exception throwing code
  28. // and added proper return code for
  29. // each method.
  30. //
  31. // 07/26/94 AlokS Made it real light weight for simple
  32. // registry set/get operations
  33. //
  34. // Notes: see notes in registry.hxx
  35. //
  36. //----------------------------------------------------------------------------
  37. #include "headers.hxx"
  38. #pragma hdrstop
  39. #include <stdlib.h>
  40. #include <windows.h>
  41. #include <registry.hxx>
  42. //+-------------------------------------------------------------------------
  43. //
  44. // Member: CRegKey::CRegKey
  45. //
  46. // Synopsis: Constructor for registry key object, using HKEY for parent
  47. //
  48. // Arguments: [hkParent] - handle to parent key
  49. // [pwszPath] - pathname to key
  50. // [samDesiredAccess] - desired access rights to the key
  51. // [pwszClass] - class for the key
  52. // [dwOptions] - options for the key eg volatile or not
  53. // [pdwDisposition] - to find out if key was opened or created
  54. // [pSecurityAttributes] - used only if the key is created
  55. // [fThrowExceptionOnError] - Constructor throw exception on error
  56. //
  57. // Signals: Internal error state is set if construction fails.
  58. //
  59. // Returns: -none-
  60. //
  61. // History: 09/30/92 Rickhi Created
  62. //
  63. // Notes: All except the hkParent and pwszPath are optional parameters.
  64. //
  65. //--------------------------------------------------------------------------
  66. CRegKey::CRegKey (
  67. HKEY hkParent,
  68. const LPWSTR pwszPath,
  69. REGSAM samDesiredAccess,
  70. const LPWSTR pwszClass,
  71. DWORD dwOptions,
  72. DWORD *pdwDisposition,
  73. const LPSECURITY_ATTRIBUTES pSecurityAttributes )
  74. :_hkParent(hkParent),
  75. _hkThis(NULL),
  76. _dwErr (ERROR_SUCCESS)
  77. {
  78. _dwErr = CreateKey( _hkParent,
  79. pwszPath,
  80. samDesiredAccess,
  81. pwszClass,
  82. dwOptions,
  83. pdwDisposition,
  84. pSecurityAttributes );
  85. }
  86. //+-------------------------------------------------------------------------
  87. //
  88. // Member: CRegKey::CRegKey
  89. //
  90. // Synopsis: Constructor for registry key object, using CRegKey for parent
  91. //
  92. // Arguments: [prkParent] - ptr to Parent CRegKey
  93. // [pwszPath] - pathname to key
  94. // [samDesiredAccess] - desired access rights to the key
  95. // [pwszClass] - class for the key
  96. // [dwOptions] - options for the key eg volatile or not
  97. // [pdwDisposition] - to find out if key was opened or created
  98. // [pSecurityAttributes] - used only if the key is created
  99. // [fThrowExceptionOnError] - Constructor throw exception on error
  100. //
  101. // Signals: Internal Error state is set if error occures during construction.
  102. //
  103. // Returns: nothing
  104. //
  105. // History: 09/30/92 Rickhi Created
  106. //
  107. // Notes: All except the prkParent and pwszPath are optional parameters.
  108. //
  109. //--------------------------------------------------------------------------
  110. CRegKey::CRegKey (
  111. const CRegKey &crkParent,
  112. const LPWSTR pwszPath,
  113. REGSAM samDesiredAccess,
  114. const LPWSTR pwszClass,
  115. DWORD dwOptions,
  116. DWORD *pdwDisposition,
  117. const LPSECURITY_ATTRIBUTES pSecurityAttributes )
  118. :_hkParent(crkParent.GetHandle()),
  119. _hkThis(NULL),
  120. _dwErr(ERROR_SUCCESS)
  121. {
  122. _dwErr = CreateKey ( _hkParent,
  123. pwszPath,
  124. samDesiredAccess,
  125. pwszClass,
  126. dwOptions,
  127. pdwDisposition,
  128. pSecurityAttributes );
  129. }
  130. //+-------------------------------------------------------------------------
  131. //
  132. // Member: CRegKey::CRegKey
  133. //
  134. // Synopsis: Constructor for registry key object, using HKEY for parent
  135. // Merely opens the key, if exist
  136. //
  137. // Arguments: [hkParent] - HKEY to Parent
  138. // [dwErr] - Error code returned here
  139. // [pwszPath] - pathname to key
  140. // [samDesiredAccess] - desired access rights to the key
  141. //
  142. // Signals: Internal Error state is set if error occures during construction
  143. //
  144. // Returns: nothing
  145. //
  146. // History: 09/22/93 AlokS Created
  147. //
  148. // Notes: Check error status to determine if constructor succeeded
  149. //
  150. //--------------------------------------------------------------------------
  151. CRegKey::CRegKey (
  152. HKEY hkParent,
  153. DWORD *pdwErr,
  154. const LPWSTR pwszPath,
  155. REGSAM samDesiredAccess )
  156. :_hkParent(hkParent),
  157. _hkThis(NULL),
  158. _dwErr(ERROR_SUCCESS)
  159. {
  160. *pdwErr = _dwErr = OpenKey ( _hkParent, pwszPath, samDesiredAccess );
  161. }
  162. //+-------------------------------------------------------------------------
  163. //
  164. // Member: CRegKey::CRegKey
  165. //
  166. // Synopsis: Constructor for registry key object, using CRegKey for parent
  167. // Merely opens the key, if exist
  168. //
  169. // Arguments: [prkParent] - ptr to Parent CRegKey
  170. // [dwErr] - Error code returned here.
  171. // [pwszPath] - pathname to key
  172. // [samDesiredAccess] - desired access rights to the key
  173. //
  174. // Signals: Internal Error state is set if error occures during construction
  175. //
  176. // Returns: nothing
  177. //
  178. // History: 09/22/93 AlokS Created
  179. //
  180. // Notes: Check error status to determine if constructor succeeded
  181. //
  182. //--------------------------------------------------------------------------
  183. CRegKey::CRegKey (
  184. const CRegKey &crkParent,
  185. DWORD *pdwErr,
  186. const LPWSTR pwszPath,
  187. REGSAM samDesiredAccess )
  188. :_hkParent(crkParent.GetHandle()),
  189. _hkThis(NULL),
  190. _dwErr(ERROR_SUCCESS)
  191. {
  192. IDfsVolInlineDebOut((
  193. DEB_TRACE, "CRegKey::+CRegKey(0x%x)\n",
  194. this));
  195. *pdwErr = _dwErr = OpenKey ( _hkParent, pwszPath, samDesiredAccess );
  196. }
  197. //+-------------------------------------------------------------------------
  198. //
  199. // Member: CRegKey::~CRegKey, public
  200. //
  201. // Synopsis: Destructor for registry key object
  202. //
  203. // Arguments: none
  204. //
  205. // Signals: nothing
  206. //
  207. // Returns: nothing
  208. //
  209. // History: 09/30/92 Rickhi Created
  210. //
  211. // Notes:
  212. //
  213. //--------------------------------------------------------------------------
  214. CRegKey::~CRegKey()
  215. {
  216. IDfsVolInlineDebOut((
  217. DEB_TRACE, "CRegKey::~CRegKey(0x%x)\n",
  218. this));
  219. if (_hkThis != NULL) {
  220. RegCloseKey(_hkThis);
  221. }
  222. }
  223. //+-------------------------------------------------------------------------
  224. //
  225. // Member: CRegKey::CreateKey, private
  226. //
  227. // Synopsis: This method does the real work of the constructors.
  228. //
  229. // Arguments: [hkParent] - handle to parent key
  230. // [pwszPath] - pathname to key
  231. // [samDesiredAccess] - desired access rights to the key
  232. // [pwszClass] - class for the key
  233. // [dwOptions] - options for the key eg volatile or not
  234. // [pdwDisposition] - to find out if key was opened or created
  235. // [pSecurityAttributes] - used only if the key is created
  236. //
  237. // Signals: -none-
  238. //
  239. // Returns: ERROR_SUCCESS on success. Else error from either Registry APIs
  240. // or from Memory allocation
  241. //
  242. // History: 09/30/92 Rickhi Created
  243. //
  244. // Notes: All parameters are required.
  245. //
  246. //--------------------------------------------------------------------------
  247. DWORD CRegKey::CreateKey (
  248. HKEY hkParent,
  249. const LPWSTR pwszPath,
  250. REGSAM samDesiredAccess,
  251. const LPWSTR pwszClass,
  252. DWORD dwOptions,
  253. DWORD *pdwDisposition,
  254. const LPSECURITY_ATTRIBUTES pSecurityAttributes )
  255. {
  256. DWORD dwDisposition;
  257. DWORD dwRc;
  258. DWORD dwErr = ERROR_SUCCESS;
  259. LPSECURITY_ATTRIBUTES lpsec = pSecurityAttributes;
  260. // create/open the key
  261. if ((dwRc = RegCreateKeyEx(hkParent,
  262. pwszPath, // path to key
  263. 0, // title index
  264. pwszClass, // class of key
  265. dwOptions, // key options
  266. samDesiredAccess, // desired access
  267. lpsec, // if created
  268. &_hkThis, // handle
  269. &dwDisposition) // opened/created
  270. )==ERROR_SUCCESS)
  271. {
  272. // save away the name
  273. _cwszName.Set(pwszPath);
  274. // setup the return parameters
  275. if (pdwDisposition != NULL)
  276. *pdwDisposition = dwDisposition;
  277. }
  278. else
  279. dwErr = Creg_ERROR(dwRc);
  280. return(dwErr);
  281. }
  282. //+-------------------------------------------------------------------------
  283. //
  284. // Member: CRegKey::OpenKey, private
  285. //
  286. // Synopsis: This method does the real work of the constructors.
  287. //
  288. // Arguments: [hkParent] - handle to parent key
  289. // [pwszPath] - pathname to key
  290. // [samDesiredAccess] - desired access rights to the key
  291. //
  292. // Signals: -none-
  293. //
  294. // Returns: ERROR_SUCCESS on success. Else error from either Registry APIs
  295. // or from Memory allocation
  296. //
  297. // History: 09/22/93 AlokS Created
  298. //
  299. // Notes: All parameters are required.
  300. //
  301. //--------------------------------------------------------------------------
  302. DWORD CRegKey::OpenKey (
  303. HKEY hkParent,
  304. const LPWSTR pwszPath,
  305. REGSAM samDesiredAccess )
  306. {
  307. DWORD dwRc;
  308. DWORD dwErr = ERROR_SUCCESS;
  309. // open the key
  310. if ((dwRc = RegOpenKeyEx(hkParent,
  311. pwszPath, // path to key
  312. 0, // reserved
  313. samDesiredAccess, // desired access
  314. &_hkThis // handle
  315. ))==ERROR_SUCCESS)
  316. {
  317. // save away the name
  318. _cwszName.Set(pwszPath);
  319. }
  320. else
  321. dwErr = Creg_ERROR(dwRc);
  322. return(dwErr);
  323. }
  324. //+-------------------------------------------------------------------------
  325. //
  326. // Member: CRegKey::Delete, public
  327. //
  328. // Synopsis: Deletes an existing key from the registry. Note that
  329. // the key object still exists, the destructor must be
  330. // called seperately.
  331. //
  332. // Arguments: none
  333. //
  334. // Signals: -none-
  335. //
  336. // Returns: ERROR_SUCCESS on success. Else error from either Registry APIs
  337. // or from Memory allocation
  338. //
  339. // History: 09/30/92 Rickhi Created
  340. //
  341. // Notes:
  342. //
  343. //--------------------------------------------------------------------------
  344. DWORD CRegKey::Delete(void)
  345. {
  346. DWORD dwErr = ERROR_SUCCESS;
  347. DWORD dwRc;
  348. SRegKeySet *pChildren;
  349. dwErr = this->EnumKeys(&pChildren);
  350. if (dwErr == ERROR_SUCCESS) {
  351. ULONG i;
  352. DWORD dwErrDelete = ERROR_SUCCESS;
  353. for(i = 0; i < pChildren->cKeys; i++) {
  354. dwErr = pChildren->aprkKey[i]->Delete();
  355. if (dwErr != ERROR_SUCCESS) {
  356. dwErrDelete = dwErr;
  357. }
  358. delete pChildren->aprkKey[i];
  359. }
  360. if (dwErrDelete == ERROR_SUCCESS) {
  361. if (( dwRc= RegDeleteKey(_hkThis, NULL))!=ERROR_SUCCESS) {
  362. dwErr = Creg_ERROR(dwRc);
  363. }
  364. } else {
  365. dwErr = dwErrDelete;
  366. }
  367. delete pChildren;
  368. }
  369. return(dwErr);
  370. }
  371. //+-------------------------------------------------------------------------
  372. //
  373. // Member: CRegKey::EnumValues, public
  374. //
  375. // Synopsis: Enumerates the values stored in an open registry key.
  376. //
  377. // Arguments: [pprvs] - SRegValueSet allocated and returned by this
  378. // method. The caller is responsible for releasing
  379. // the allocated CRegValue objects via delete and the
  380. // SRegValueSet structure via CRegKey::MemFree.
  381. //
  382. // Signals: none
  383. //
  384. // Returns: ERROR_SUCCESS on success. Else error from either Registry APIs
  385. // or from Memory allocation
  386. //
  387. // History: 09/30/92 Rickhi Created
  388. //
  389. // Notes: The data associated with each Value is not returned. The
  390. // caller may invoke the GetValue method of each CRegValue
  391. // returned to get it's associated data.
  392. //
  393. //--------------------------------------------------------------------------
  394. DWORD CRegKey::EnumValues(SRegValueSet **pprvs)
  395. {
  396. DWORD dwErr = ERROR_SUCCESS;
  397. // figure out how many values are currently stored in this key
  398. // and allocate a buffer to hold the return results.
  399. WCHAR wszClass[MAX_PATH];
  400. ULONG cbClass = sizeof(wszClass);
  401. ULONG cSubKeys, cbMaxSubKeyLen, cbMaxClassLen;
  402. ULONG cValues, cbMaxValueIDLen, cbMaxValueLen;
  403. SECURITY_DESCRIPTOR SecDescriptor;
  404. FILETIME ft;
  405. DWORD dwRc = RegQueryInfoKey(_hkThis,
  406. wszClass,
  407. &cbClass,
  408. NULL,
  409. &cSubKeys,
  410. &cbMaxSubKeyLen,
  411. &cbMaxClassLen,
  412. &cValues,
  413. &cbMaxValueIDLen,
  414. &cbMaxValueLen,
  415. (DWORD *)&SecDescriptor,
  416. &ft );
  417. if ( dwRc == ERROR_SUCCESS )
  418. {
  419. *pprvs = (SRegValueSet *) new BYTE [ sizeof(SRegValueSet)+
  420. cValues*sizeof(CRegValue *) ];
  421. if ( *pprvs == NULL )
  422. {
  423. dwErr = ERROR_OUTOFMEMORY;
  424. }
  425. }
  426. else
  427. {
  428. // QueryInfo failed.
  429. dwErr = Creg_ERROR(dwRc);
  430. }
  431. if (dwErr != ERROR_SUCCESS)
  432. {
  433. return(dwErr);
  434. }
  435. // loop enumerating and creating a RegValue object for each value
  436. DWORD dwIndex=0;
  437. do
  438. {
  439. WCHAR wszValueID[MAX_PATH];
  440. ULONG cbValueID = MAX_PATH;
  441. DWORD dwTypeCode;
  442. CRegValue *pRegVal;
  443. if ((dwRc = RegEnumValue(_hkThis, // handle
  444. dwIndex, // index
  445. wszValueID, // value id
  446. &cbValueID, // length of value name
  447. NULL, // title index
  448. &dwTypeCode, // data type
  449. NULL, // data buffer
  450. NULL // size of data buffer
  451. ))==ERROR_SUCCESS)
  452. {
  453. // create the appropriate class of value object
  454. switch (dwTypeCode)
  455. {
  456. case REG_SZ:
  457. pRegVal = (CRegValue *) new CRegSZ((const CRegKey &)*this, wszValueID);
  458. break;
  459. case REG_DWORD:
  460. pRegVal = (CRegValue *) new CRegDWORD((const CRegKey &)*this, wszValueID);
  461. break;
  462. case REG_BINARY:
  463. pRegVal = (CRegValue *) new CRegBINARY((const CRegKey &)*this, wszValueID);
  464. break;
  465. default:
  466. pRegVal = (CRegValue *) new CRegBINARY((const CRegKey &)*this, wszValueID);
  467. break;
  468. }
  469. // save ptr to value object and count another entry
  470. (*pprvs)->aprvValue[dwIndex++] = pRegVal;
  471. }
  472. else
  473. {
  474. // error, we're done with the enumeration
  475. break;
  476. }
  477. } while (dwIndex < cValues);
  478. // finished the enumeration, check the results
  479. if (dwRc == ERROR_NO_MORE_ITEMS || dwRc == ERROR_SUCCESS)
  480. {
  481. // set the return count
  482. (*pprvs)->cValues = dwIndex;
  483. }
  484. else
  485. {
  486. // Cleanup and return an error
  487. while (dwIndex)
  488. {
  489. delete (*pprvs)->aprvValue[--dwIndex];
  490. }
  491. delete [] *pprvs;
  492. dwErr = Creg_ERROR(dwRc);
  493. }
  494. return(dwErr);
  495. }
  496. //+-------------------------------------------------------------------------
  497. //
  498. // Member: CRegKey::EnumKeys, public
  499. //
  500. // Synopsis: Enumerates the subkeys of an open registry key.
  501. //
  502. // Arguments: [pprks] - SRegKeySet allocated and returned by this method.
  503. // The caller is responsible for releasing all the
  504. // allocated CRegKey objects and the SRegKeySet
  505. // structure.
  506. //
  507. // Signals: none
  508. //
  509. // Returns: ERROR_SUCCESS on success. Else error from either Registry APIs
  510. // or from Memory allocation
  511. //
  512. // History: 09/30/92 Rickhi Created
  513. //
  514. // Notes:
  515. //
  516. //--------------------------------------------------------------------------
  517. DWORD CRegKey::EnumKeys(SRegKeySet **pprks)
  518. {
  519. // figure out how many keys are currently stored in this key
  520. // and allocate a buffer to hold the return results.
  521. WCHAR wszClass[MAX_PATH];
  522. ULONG cbClass = sizeof(wszClass);
  523. ULONG cSubKeys, cbMaxSubKeyLen, cbMaxClassLen;
  524. ULONG cValues, cbMaxValueIDLen, cbMaxValueLen;
  525. SECURITY_DESCRIPTOR SecDescriptor;
  526. FILETIME ft;
  527. DWORD dwErr = ERROR_SUCCESS;
  528. DWORD dwRc = RegQueryInfoKey(_hkThis,
  529. wszClass,
  530. &cbClass,
  531. NULL,
  532. &cSubKeys,
  533. &cbMaxSubKeyLen,
  534. &cbMaxClassLen,
  535. &cValues,
  536. &cbMaxValueIDLen,
  537. &cbMaxValueLen,
  538. (DWORD *)&SecDescriptor,
  539. &ft);
  540. if ( dwRc == ERROR_SUCCESS )
  541. {
  542. *pprks = (SRegKeySet*) new BYTE [sizeof(SRegKeySet)+cSubKeys*sizeof(CRegKey *)];
  543. if ( *pprks == NULL )
  544. {
  545. dwErr = ERROR_OUTOFMEMORY;
  546. }
  547. }
  548. else
  549. {
  550. // QueryInfo failed..
  551. dwErr = Creg_ERROR(dwRc);
  552. }
  553. if (dwErr != ERROR_SUCCESS)
  554. {
  555. return(dwErr);
  556. }
  557. // loop enumerating and creating a RegKey object for each subkey
  558. DWORD dwIndex=0;
  559. do
  560. {
  561. WCHAR wszKeyName[MAX_PATH];
  562. ULONG cbKeyName = MAX_PATH;
  563. WCHAR wszClass[MAX_PATH];
  564. ULONG cbClass = MAX_PATH;
  565. FILETIME ft;
  566. if ((dwRc = RegEnumKeyEx(_hkThis, // handle
  567. dwIndex, // index
  568. wszKeyName, // key name
  569. &cbKeyName, // length of key name
  570. NULL, // title index
  571. wszClass, // class
  572. &cbClass, // length of class
  573. &ft // last write time
  574. ))==ERROR_SUCCESS)
  575. {
  576. // Create a CRegKey object for the subkey
  577. CRegKey *pRegKey = (CRegKey *) new CRegKey((const CRegKey &)*this, wszKeyName);
  578. // bug 447481: check for null return from above.
  579. if (pRegKey == NULL)
  580. {
  581. dwErr = ERROR_OUTOFMEMORY;
  582. break;
  583. }
  584. if (ERROR_SUCCESS != (dwErr = pRegKey->QueryErrorStatus()))
  585. {
  586. break;
  587. }
  588. (*pprks)->aprkKey[dwIndex++] = pRegKey;
  589. }
  590. else
  591. {
  592. // error, we're done with the enumeration
  593. break;
  594. }
  595. } while (dwIndex < cSubKeys);
  596. // finished the enumeration, check the results
  597. if ((dwErr == ERROR_SUCCESS) &&
  598. ((dwRc == ERROR_NO_MORE_ITEMS || dwRc == ERROR_SUCCESS)))
  599. {
  600. // set the return count
  601. (*pprks)->cKeys = dwIndex;
  602. }
  603. else
  604. {
  605. // Cleanup and return an error
  606. while (dwIndex)
  607. {
  608. delete (*pprks)->aprkKey[--dwIndex];
  609. }
  610. delete [] *pprks;
  611. dwErr = Creg_ERROR(dwRc);
  612. }
  613. return(dwErr);
  614. }
  615. //+-------------------------------------------------------------------------
  616. //
  617. // Member: CRegValue::GetValue, public
  618. //
  619. // Purpose: Returns the data associated with a registry value.
  620. //
  621. // Arguements: [pbData] - ptr to buffer supplied by caller.
  622. // [cbData] - size of data buffer supplied.
  623. // [pdwTypeCode] - type of data returned.
  624. //
  625. // Signals:
  626. //
  627. // Returns: ERROR_SUCCESS on success. Else error from either Registry APIs
  628. // or from Memory allocation
  629. //
  630. // History: 09/30/92 Rickhi Created
  631. //
  632. // Notes:
  633. //
  634. //
  635. //
  636. //--------------------------------------------------------------------------
  637. DWORD CRegValue::GetValue(LPBYTE pbData, ULONG* pcbData, DWORD *pdwTypeCode)
  638. {
  639. DWORD dwRc = RegQueryValueEx(GetParentHandle(),
  640. (LPWSTR)_cwszValueID, // value id
  641. NULL, // title index
  642. pdwTypeCode, // type of data returned
  643. pbData, // data
  644. pcbData); // size of data
  645. return(dwRc);
  646. }
  647. //+-------------------------------------------------------------------------
  648. //
  649. // Member: CRegValue::SetValue
  650. //
  651. // Purpose: Writes the data associated with a registry value.
  652. //
  653. // Arguements: [pbData] - ptr to data to write.
  654. // [cbData] - size of data to write.
  655. // [dwTypeCode] - type of data to write.
  656. //
  657. // Signals: -none-
  658. //
  659. // Returns: ERROR_SUCCESS on success. Else error from either Registry APIs
  660. // or from Memory allocation
  661. //
  662. // History: 09/30/92 Rickhi Created
  663. //
  664. // Notes:
  665. //
  666. //--------------------------------------------------------------------------
  667. DWORD CRegValue::SetValue(const LPBYTE pbData, ULONG cbData, DWORD dwTypeCode)
  668. {
  669. DWORD dwRc;
  670. DWORD dwErr = ERROR_SUCCESS;
  671. if ((dwRc = RegSetValueEx(GetParentHandle(), // key handle
  672. (LPWSTR)_cwszValueID, // value id
  673. NULL, // title index
  674. dwTypeCode, // type of info in buffer
  675. pbData, // data
  676. cbData) // size of data
  677. )!= ERROR_SUCCESS)
  678. {
  679. dwErr = Creg_ERROR(dwRc);
  680. }
  681. return(dwErr);
  682. }
  683. //+-------------------------------------------------------------------------
  684. //
  685. // Function: DelRegKeyTree
  686. //
  687. // Purpose: Deletes a key and any of it's children. This is like
  688. // delnode for registry
  689. //
  690. // Arguements: [hParent] - Handle to Parent Key
  691. // [lpwszKeyPath] - Path (relative to Parent) of the key
  692. //
  693. // Signals:
  694. //
  695. // Returns: ERROR_SUCCESS on success. Else error from either Registry APIs
  696. // or from Memory allocation
  697. //
  698. // History: 09/30/93 AlokS Created
  699. //
  700. // Notes:
  701. //
  702. //--------------------------------------------------------------------------
  703. DWORD DelRegKeyTree ( HKEY hParent, LPWSTR lpwszKeyPath)
  704. {
  705. DWORD dwErr = ERROR_SUCCESS;
  706. CRegKey cregKey ( hParent,
  707. lpwszKeyPath
  708. );
  709. if (ERROR_SUCCESS != (dwErr = cregKey.QueryErrorStatus()))
  710. {
  711. return(dwErr);
  712. }
  713. // Enumerate the children of the key. We will
  714. // not propogate to the caller errors from enumeration
  715. SRegKeySet *pRegKeySet = NULL;
  716. if (ERROR_SUCCESS == (dwErr = cregKey.EnumKeys ( & pRegKeySet)))
  717. {
  718. // Now we have set of Keys which need to be deleted in depth
  719. // first manner
  720. for (ULONG i = 0; i < pRegKeySet->cKeys; i++ )
  721. {
  722. dwErr = DelRegKeyTree ( cregKey.GetHandle(),
  723. pRegKeySet->aprkKey[i]->GetName()
  724. );
  725. // Delete the key itself
  726. delete pRegKeySet->aprkKey[i];
  727. }
  728. // Delete the enumerator structure
  729. delete pRegKeySet;
  730. }
  731. // Finally delete this key
  732. dwErr = cregKey.Delete();
  733. return(dwErr);
  734. }
  735. DWORD CRegKey::DeleteChildren()
  736. {
  737. // figure out how many keys are currently stored in this key
  738. ULONG cSubKeys, cbMaxSubKeyLen;
  739. DWORD dwErr = ERROR_SUCCESS;
  740. DWORD dwRc = RegQueryInfoKey(_hkThis,
  741. NULL,
  742. NULL,
  743. NULL,
  744. &cSubKeys,
  745. &cbMaxSubKeyLen,
  746. NULL,
  747. NULL,
  748. NULL,
  749. NULL,
  750. NULL,
  751. NULL);
  752. if ( dwRc != ERROR_SUCCESS )
  753. {
  754. // QueryInfo failed..
  755. dwErr = Creg_ERROR(dwRc);
  756. }
  757. if (dwErr != ERROR_SUCCESS)
  758. {
  759. return(dwErr);
  760. }
  761. // loop enumerating and creating a RegKey object for each subkey
  762. DWORD dwIndex=0;
  763. do
  764. {
  765. WCHAR wszKeyName[MAX_PATH];
  766. ULONG cbKeyName = sizeof(wszKeyName);
  767. FILETIME ft;
  768. if ((dwRc = RegEnumKeyEx(_hkThis, // handle
  769. dwIndex, // index
  770. wszKeyName, // key name
  771. &cbKeyName, // length of key name
  772. NULL, // title index
  773. NULL, // class
  774. NULL, // length of class
  775. &ft // last write time
  776. ))==ERROR_SUCCESS)
  777. {
  778. // Create a CRegKey object for the subkey
  779. CRegKey *pRegKey = (CRegKey *) new CRegKey((const CRegKey &)*this, wszKeyName);
  780. if (ERROR_SUCCESS != (dwErr = pRegKey->QueryErrorStatus()))
  781. {
  782. break;
  783. }
  784. pRegKey->DeleteChildren();
  785. delete pRegKey;
  786. dwRc = RegDeleteKey(_hkThis, wszKeyName);
  787. }
  788. else
  789. {
  790. // error, we're done with the enumeration
  791. break;
  792. }
  793. } while (dwIndex < cSubKeys);
  794. // finished the enumeration, check the results
  795. if ((dwErr == ERROR_SUCCESS) &&
  796. (dwRc != ERROR_NO_MORE_ITEMS && dwRc != ERROR_SUCCESS))
  797. {
  798. dwErr = Creg_ERROR(dwRc);
  799. }
  800. return(dwErr);
  801. }