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.

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