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.

962 lines
22 KiB

  1. /**********************************************************************/
  2. /** Microsoft Windows/NT **/
  3. /** Copyright(c) Microsoft Corporation, 1995 - 1999 **/
  4. /**********************************************************************/
  5. /*
  6. FILE HISTORY:
  7. */
  8. #include <precompiled.h>
  9. #include <stdlib.h>
  10. #include <memory.h>
  11. #include <ctype.h>
  12. //#include "tfschar.h"
  13. #include "tregkey.h"
  14. #ifdef _DEBUG
  15. #undef THIS_FILE
  16. static char BASED_CODE THIS_FILE[] = __FILE__;
  17. #endif
  18. // Convert a CStringList to the REG_MULTI_SZ format
  19. DWORD StrList2MULTI_SZ(CStringList & strList, DWORD * pcbSize, BYTE ** ppbData)
  20. {
  21. DWORD dwErr = 0 ;
  22. POSITION pos ;
  23. CString * pstr ;
  24. int cbTotal = 0 ;
  25. // Walk the list accumulating sizes
  26. for ( pos = strList.GetHeadPosition() ;
  27. pos != NULL && (pstr = & strList.GetNext( pos )) ; )
  28. {
  29. cbTotal += pstr->GetLength() + 1 ;
  30. }
  31. // Add on space for two NULL characters
  32. cbTotal += 2;
  33. // Allocate and fill a temporary buffer
  34. if (*pcbSize = (cbTotal * sizeof(TCHAR) ) )
  35. {
  36. TRY
  37. {
  38. *ppbData = new BYTE[ *pcbSize] ;
  39. // NULL out the data buffer
  40. ::ZeroMemory(*ppbData, *pcbSize);
  41. BYTE * pbData = *ppbData ;
  42. // Populate the buffer with the strings.
  43. for ( pos = strList.GetHeadPosition() ;
  44. pos != NULL && (pstr = & strList.GetNext( pos )) ; )
  45. {
  46. int cb = (pstr->GetLength() + 1) * sizeof(TCHAR) ;
  47. ::memcpy( pbData, (LPCTSTR) *pstr, cb ) ;
  48. pbData += cb ;
  49. }
  50. // Assert that we have not passed the end of the buffer
  51. _ASSERTE((pbData - *ppbData) < (int) *pcbSize);
  52. // Assert that we have an extra NULL character
  53. _ASSERTE(*((TCHAR *)pbData) == 0);
  54. }
  55. CATCH_ALL(e)
  56. {
  57. dwErr = ERROR_NOT_ENOUGH_MEMORY ;
  58. }
  59. END_CATCH_ALL
  60. }
  61. else
  62. {
  63. *ppbData = NULL;
  64. }
  65. return dwErr ;
  66. }
  67. // Convert a REG_MULTI_SZ format to the CStringList
  68. DWORD MULTI_SZ2StrList(LPCTSTR pstrMulti_Sz, CStringList& strList)
  69. {
  70. DWORD dwErr = NOERROR;
  71. strList.RemoveAll();
  72. // Catch exceptions trying to build the list
  73. TRY
  74. {
  75. if (pstrMulti_Sz)
  76. {
  77. while ( lstrlen(pstrMulti_Sz) )
  78. {
  79. strList.AddTail( pstrMulti_Sz ) ;
  80. pstrMulti_Sz += lstrlen( pstrMulti_Sz ) + 1 ;
  81. }
  82. }
  83. }
  84. CATCH_ALL(e)
  85. {
  86. dwErr = ERROR_NOT_ENOUGH_MEMORY ;
  87. }
  88. END_CATCH_ALL
  89. return dwErr;
  90. }
  91. /*!--------------------------------------------------------------------------
  92. RegKey::RegKey
  93. Constructor
  94. Author: KennT
  95. ---------------------------------------------------------------------------*/
  96. RegKey::RegKey()
  97. : m_hKey(0)
  98. {
  99. }
  100. /*!--------------------------------------------------------------------------
  101. RegKey::~RegKey
  102. Destructor
  103. Author: KennT
  104. ---------------------------------------------------------------------------*/
  105. RegKey::~RegKey ()
  106. {
  107. Close();
  108. }
  109. /*!--------------------------------------------------------------------------
  110. RegKey::Open
  111. Author: KennT
  112. ---------------------------------------------------------------------------*/
  113. DWORD RegKey::Open( HKEY hKeyParent,
  114. LPCTSTR pszSubKey,
  115. REGSAM regSam,
  116. LPCTSTR pszServerName)
  117. {
  118. HKEY hkBase = NULL ;
  119. DWORD dwErr = 0;
  120. Close();
  121. // If we have a server name, try to open a remote connection
  122. if ( pszServerName )
  123. dwErr = ::RegConnectRegistry((LPTSTR) pszServerName, hKeyParent, &hkBase);
  124. else
  125. hkBase = hKeyParent ;
  126. if ( dwErr == 0 )
  127. {
  128. if ( pszSubKey )
  129. {
  130. dwErr = ::RegOpenKeyEx( hkBase, pszSubKey, 0, regSam, & m_hKey ) ;
  131. }
  132. else
  133. {
  134. m_hKey = hkBase ;
  135. hkBase = NULL ; // set to NULL so that the key doesn't get closed
  136. }
  137. if ( hkBase && (hkBase != hKeyParent) )
  138. ::RegCloseKey( hkBase ) ;
  139. }
  140. if ( dwErr )
  141. m_hKey = NULL ;
  142. return dwErr;
  143. }
  144. /*!--------------------------------------------------------------------------
  145. RegKey::Create
  146. -
  147. Author: KennT
  148. ---------------------------------------------------------------------------*/
  149. DWORD RegKey::Create(
  150. HKEY hKeyBase,
  151. LPCTSTR pszSubKey,
  152. DWORD dwOptions,
  153. REGSAM regSam,
  154. LPSECURITY_ATTRIBUTES pSecAttr,
  155. LPCTSTR pszServerName )
  156. {
  157. HKEY hkBase = NULL ;
  158. LONG dwErr = 0;
  159. DWORD dwDisposition;
  160. Close();
  161. if ( pszServerName )
  162. {
  163. // This is a remote connection.
  164. dwErr = ::RegConnectRegistry( (LPTSTR) pszServerName, hKeyBase, &hkBase );
  165. }
  166. else
  167. hkBase = hKeyBase ;
  168. if (dwErr == 0)
  169. {
  170. LPTSTR szEmpty = _T("");
  171. dwErr = ::RegCreateKeyEx( hkBase, pszSubKey,
  172. 0, szEmpty,
  173. dwOptions, regSam, pSecAttr,
  174. & m_hKey,
  175. & dwDisposition ) ;
  176. if ( hkBase && (hkBase != hKeyBase) )
  177. ::RegCloseKey( hkBase ) ;
  178. }
  179. if ( dwErr )
  180. m_hKey = NULL ;
  181. return dwErr;
  182. }
  183. /*!--------------------------------------------------------------------------
  184. RegKey::Close
  185. -
  186. Author: KennT
  187. ---------------------------------------------------------------------------*/
  188. DWORD RegKey::Close()
  189. {
  190. DWORD dwErr = 0;
  191. if (m_hKey)
  192. dwErr = ::RegCloseKey(m_hKey);
  193. m_hKey = 0;
  194. return dwErr;
  195. }
  196. /*!--------------------------------------------------------------------------
  197. RegKey::Detach
  198. -
  199. Author: KennT
  200. ---------------------------------------------------------------------------*/
  201. HKEY RegKey::Detach()
  202. {
  203. HKEY hKey = m_hKey;
  204. m_hKey = NULL;
  205. return hKey;
  206. }
  207. /*!--------------------------------------------------------------------------
  208. RegKey::Attach
  209. -
  210. Author: KennT
  211. ---------------------------------------------------------------------------*/
  212. void RegKey::Attach(HKEY hKey)
  213. {
  214. _ASSERTE(m_hKey == NULL);
  215. m_hKey = hKey;
  216. }
  217. /*!--------------------------------------------------------------------------
  218. RegKey::DeleteSubKey
  219. -
  220. Author: KennT
  221. ---------------------------------------------------------------------------*/
  222. DWORD RegKey::DeleteSubKey(LPCTSTR lpszSubKey)
  223. {
  224. _ASSERTE(m_hKey != NULL);
  225. return RegDeleteKey(m_hKey, lpszSubKey);
  226. }
  227. /*!--------------------------------------------------------------------------
  228. RegKey::DeleteValue
  229. -
  230. Author: KennT
  231. ---------------------------------------------------------------------------*/
  232. DWORD RegKey::DeleteValue(LPCTSTR lpszValue)
  233. {
  234. _ASSERTE(m_hKey != NULL);
  235. return RegDeleteValue(m_hKey, (LPTSTR)lpszValue);
  236. }
  237. /*!--------------------------------------------------------------------------
  238. RegKey::RecurseDeleteKey
  239. -
  240. Author: KennT
  241. ---------------------------------------------------------------------------*/
  242. DWORD RegKey::RecurseDeleteKey(LPCTSTR lpszKey)
  243. {
  244. RegKey key;
  245. DWORD dwRes = key.Open(m_hKey, lpszKey, KEY_READ | KEY_WRITE);
  246. if (dwRes != ERROR_SUCCESS)
  247. return dwRes;
  248. FILETIME time;
  249. TCHAR szBuffer[256];
  250. DWORD dwSize = 256;
  251. while (RegEnumKeyEx(key, 0, szBuffer, &dwSize, NULL, NULL, NULL,
  252. &time)==ERROR_SUCCESS)
  253. {
  254. dwRes = key.RecurseDeleteKey(szBuffer);
  255. if (dwRes != ERROR_SUCCESS)
  256. return dwRes;
  257. dwSize = 256;
  258. }
  259. key.Close();
  260. return DeleteSubKey(lpszKey);
  261. }
  262. /*!--------------------------------------------------------------------------
  263. RegKey::RecurseDeleteSubKeys
  264. Deletes the subkeys of the current key.
  265. Author: KennT
  266. ---------------------------------------------------------------------------*/
  267. DWORD RegKey::RecurseDeleteSubKeys()
  268. {
  269. FILETIME time;
  270. TCHAR szBuffer[256];
  271. DWORD dwSize = 256;
  272. DWORD dwRes;
  273. while (RegEnumKeyEx(m_hKey, 0, szBuffer, &dwSize, NULL, NULL, NULL,
  274. &time)==ERROR_SUCCESS)
  275. {
  276. dwRes = RecurseDeleteKey(szBuffer);
  277. if (dwRes != ERROR_SUCCESS)
  278. return dwRes;
  279. dwSize = 256;
  280. }
  281. return ERROR_SUCCESS;
  282. }
  283. /*!--------------------------------------------------------------------------
  284. RegKey::PrepareValue
  285. Prepare to read a value by finding the value's size. This will
  286. allocate space for the data. The data needs to be freed separately
  287. by 'delete'.
  288. Author: KennT
  289. ---------------------------------------------------------------------------*/
  290. DWORD RegKey::PrepareValue( LPCTSTR pszValueName,
  291. DWORD * pdwType,
  292. DWORD * pcbSize,
  293. BYTE ** ppbData )
  294. {
  295. DWORD dwErr = 0;
  296. BYTE chDummy[2] ;
  297. DWORD cbData = 0 ;
  298. do
  299. {
  300. // Set the resulting buffer size to 0.
  301. *pcbSize = 0 ;
  302. *ppbData = NULL ;
  303. dwErr = ::RegQueryValueEx( m_hKey,
  304. pszValueName,
  305. 0, pdwType,
  306. chDummy, & cbData ) ;
  307. // The only error we should get here is ERROR_MORE_DATA, but
  308. // we may get no error if the value has no data.
  309. if ( dwErr == 0 )
  310. {
  311. cbData = sizeof (LONG) ; // Just a fudgy number
  312. }
  313. else
  314. if ( dwErr != ERROR_MORE_DATA )
  315. break ;
  316. // Allocate a buffer large enough for the data.
  317. *ppbData = new BYTE [ (*pcbSize = cbData) + sizeof (LONG) ] ;
  318. _ASSERTE(*ppbData);
  319. // Now that have a buffer, re-fetch the value.
  320. dwErr = ::RegQueryValueEx( m_hKey,
  321. pszValueName,
  322. 0, pdwType,
  323. *ppbData, &cbData ) ;
  324. } while ( FALSE ) ;
  325. if ( dwErr )
  326. {
  327. delete [] *ppbData ;
  328. *ppbData = NULL;
  329. *pcbSize = 0;
  330. }
  331. return dwErr ;
  332. }
  333. DWORD RegKey::QueryTypeAndSize(LPCTSTR pszValueName, DWORD *pdwType, DWORD *pdwSize)
  334. {
  335. return ::RegQueryValueEx(m_hKey, pszValueName, NULL, pdwType,
  336. NULL, pdwSize);
  337. }
  338. DWORD RegKey::QueryValueExplicit(LPCTSTR pszValueName,
  339. DWORD *pdwType,
  340. DWORD *pdwSize,
  341. LPBYTE *ppbData)
  342. {
  343. DWORD dwErr = 0;
  344. DWORD dwType;
  345. DWORD cbData;
  346. BYTE * pbData = NULL;
  347. _ASSERTE(pdwType);
  348. _ASSERTE(pdwSize);
  349. _ASSERTE(ppbData);
  350. dwErr = PrepareValue( pszValueName, &dwType, &cbData, &pbData );
  351. if (dwErr == ERROR_SUCCESS)
  352. {
  353. if (dwType != REG_MULTI_SZ)
  354. {
  355. dwErr = ERROR_INVALID_PARAMETER;
  356. }
  357. else
  358. {
  359. *pdwType = dwType;
  360. *pdwSize = cbData;
  361. *ppbData = pbData;
  362. pbData = NULL;
  363. }
  364. }
  365. delete pbData;
  366. return dwErr;
  367. }
  368. // Overloaded value query members; each returns ERROR_INVALID_PARAMETER
  369. // if data exists but not in correct form to deliver into result object.
  370. DWORD RegKey::QueryValue( LPCTSTR pszValueName, CString& strResult )
  371. {
  372. DWORD dwErr = 0;
  373. DWORD dwType ;
  374. DWORD cbData ;
  375. BYTE * pabData = NULL ;
  376. do
  377. {
  378. if ( dwErr = PrepareValue( pszValueName, &dwType, &cbData, &pabData ) )
  379. break ;
  380. if (( dwType != REG_SZ ) && (dwType != REG_EXPAND_SZ))
  381. {
  382. dwErr = ERROR_INVALID_PARAMETER ;
  383. break ;
  384. }
  385. // Guarantee that the data looks like a string
  386. pabData[cbData] = 0 ;
  387. // Catch exceptions trying to assign to the caller's string
  388. TRY
  389. {
  390. strResult = (LPCTSTR) pabData ;
  391. }
  392. CATCH_ALL(e)
  393. {
  394. dwErr = ERROR_NOT_ENOUGH_MEMORY ;
  395. }
  396. END_CATCH_ALL
  397. }
  398. while ( FALSE ) ;
  399. delete [] pabData ;
  400. return dwErr ;
  401. }
  402. DWORD RegKey::QueryValue ( LPCTSTR pchValueName, CStringList & strList )
  403. {
  404. DWORD dwErr = 0 ;
  405. DWORD dwType ;
  406. DWORD cbData ;
  407. BYTE * pabData = NULL ;
  408. LPTSTR pbTemp, pbTempLimit;
  409. do
  410. {
  411. if ( dwErr = PrepareValue( pchValueName, & dwType, & cbData, & pabData ) )
  412. break ;
  413. if ( dwType != REG_MULTI_SZ )
  414. {
  415. dwErr = ERROR_INVALID_PARAMETER ;
  416. break ;
  417. }
  418. // Guarantee that the trailing data looks like a string
  419. pabData[cbData] = 0 ;
  420. pbTemp = (LPTSTR) pabData ;
  421. pbTempLimit = & pbTemp[MaxCchFromCb(cbData)-1] ;
  422. dwErr = MULTI_SZ2StrList(pbTemp, strList);
  423. }
  424. while ( FALSE ) ;
  425. delete [] pabData ;
  426. return dwErr ;
  427. }
  428. /*!--------------------------------------------------------------------------
  429. RegKey::QueryValue
  430. Gets the DWORD value for this key. Returns ERROR_INVALID_PARAMETER
  431. if the value is not a REG_DWORD.
  432. Author: KennT
  433. ---------------------------------------------------------------------------*/
  434. DWORD RegKey::QueryValue( LPCTSTR pszValueName, DWORD& dwResult )
  435. {
  436. DWORD dwErr;
  437. DWORD cbData = sizeof(DWORD);
  438. DWORD dwType = REG_DWORD;
  439. dwErr = ::RegQueryValueEx( m_hKey,
  440. pszValueName,
  441. 0, &dwType,
  442. (LPBYTE) &dwResult, &cbData ) ;
  443. if ((dwErr == ERROR_SUCCESS) && (dwType != REG_DWORD))
  444. dwErr = ERROR_INVALID_PARAMETER;
  445. if ( dwErr )
  446. dwResult = 0;
  447. return dwErr;
  448. }
  449. DWORD RegKey::QueryValue ( LPCTSTR pchValueName, LPTSTR pszDestBuffer, DWORD cchSize, BOOL fExpandSz)
  450. {
  451. DWORD dwErr;
  452. DWORD cbData = MinCbNeededForCch(cchSize);
  453. DWORD dwType = REG_SZ;
  454. TCHAR * pszBuffer = (TCHAR *) _alloca(MinCbNeededForCch(cchSize));
  455. dwErr = ::RegQueryValueEx( m_hKey,
  456. pchValueName,
  457. 0, &dwType,
  458. (LPBYTE) pszBuffer, &cbData ) ;
  459. if ((dwErr == ERROR_SUCCESS) &&
  460. (dwType != REG_SZ) &&
  461. (dwType != REG_EXPAND_SZ) &&
  462. (dwType != REG_MULTI_SZ))
  463. dwErr = ERROR_INVALID_PARAMETER;
  464. if (dwErr == ERROR_SUCCESS)
  465. {
  466. if ((dwType == REG_EXPAND_SZ) && fExpandSz)
  467. ExpandEnvironmentStrings(pszBuffer, pszDestBuffer, cchSize);
  468. else
  469. ::CopyMemory(pszDestBuffer, pszBuffer, cbData);
  470. }
  471. return dwErr;
  472. }
  473. DWORD RegKey::QueryValue ( LPCTSTR pszValueName, CByteArray & abResult )
  474. {
  475. DWORD dwErr = 0 ;
  476. DWORD dwType ;
  477. DWORD cbData ;
  478. BYTE * pabData = NULL ;
  479. do
  480. {
  481. if ( dwErr = PrepareValue( pszValueName, & dwType, & cbData, & pabData ) )
  482. break ;
  483. if ( dwType != REG_BINARY )
  484. {
  485. dwErr = ERROR_INVALID_PARAMETER ;
  486. break ;
  487. }
  488. // Catch exceptions trying to grow the result array
  489. TRY
  490. {
  491. abResult.SetSize( cbData ) ;
  492. }
  493. CATCH_ALL(e)
  494. {
  495. dwErr = ERROR_NOT_ENOUGH_MEMORY ;
  496. }
  497. END_CATCH_ALL
  498. if ( dwErr )
  499. break ;
  500. // Move the data to the result array.
  501. for ( DWORD i = 0 ; i < cbData ; i++ )
  502. {
  503. abResult[i] = pabData[i] ;
  504. }
  505. }
  506. while ( FALSE ) ;
  507. // Memory leak....
  508. //if ( dwErr )
  509. //{
  510. delete [] pabData ;
  511. //}
  512. return dwErr ;
  513. }
  514. DWORD RegKey::QueryValue ( LPCTSTR pszValueName, void * pvResult, DWORD cbSize )
  515. {
  516. DWORD dwErr;
  517. DWORD dwType = REG_BINARY;
  518. dwErr = ::RegQueryValueEx( m_hKey,
  519. pszValueName,
  520. 0, &dwType,
  521. (LPBYTE) pvResult, &cbSize ) ;
  522. if ((dwErr == ERROR_SUCCESS) && (dwType != REG_BINARY))
  523. dwErr = ERROR_INVALID_PARAMETER;
  524. return dwErr;
  525. }
  526. DWORD RegKey::SetValueExplicit(LPCTSTR pszValueName,
  527. DWORD dwType,
  528. DWORD dwSize,
  529. LPBYTE pbData)
  530. {
  531. return ::RegSetValueEx( *this,
  532. pszValueName,
  533. 0,
  534. dwType,
  535. pbData,
  536. dwSize);
  537. }
  538. // Overloaded value setting members.
  539. DWORD RegKey::SetValue ( LPCTSTR pszValueName, LPCTSTR pszValue,
  540. BOOL fRegExpand)
  541. {
  542. DWORD dwErr = 0;
  543. DWORD dwType = fRegExpand ? REG_EXPAND_SZ : REG_SZ;
  544. dwErr = ::RegSetValueEx( *this,
  545. pszValueName,
  546. 0,
  547. dwType,
  548. (const BYTE *) pszValue,
  549. // This is not the correct string length
  550. // for DBCS strings
  551. pszValue ? CbStrLen(pszValue) : 0);
  552. return dwErr ;
  553. }
  554. DWORD RegKey::SetValue ( LPCTSTR pszValueName, CStringList & strList )
  555. {
  556. DWORD dwErr = 0;
  557. DWORD cbSize ;
  558. BYTE * pbData = NULL ;
  559. dwErr = FlattenValue( strList, & cbSize, & pbData ) ;
  560. if ( dwErr == 0 )
  561. {
  562. dwErr = ::RegSetValueEx( *this,
  563. pszValueName,
  564. 0,
  565. REG_MULTI_SZ,
  566. pbData,
  567. cbSize ) ;
  568. }
  569. delete pbData ;
  570. return dwErr ;
  571. }
  572. DWORD RegKey::SetValue ( LPCTSTR pszValueName, DWORD & dwResult )
  573. {
  574. DWORD dwErr = 0;
  575. dwErr = ::RegSetValueEx( *this,
  576. pszValueName,
  577. 0,
  578. REG_DWORD,
  579. (const BYTE *) & dwResult,
  580. sizeof dwResult ) ;
  581. return dwErr ;
  582. }
  583. DWORD RegKey::SetValue ( LPCTSTR pszValueName, CByteArray & abResult )
  584. {
  585. DWORD dwErr = 0;
  586. DWORD cbSize ;
  587. BYTE * pbData = NULL ;
  588. dwErr = FlattenValue( abResult, & cbSize, & pbData ) ;
  589. if ( dwErr == 0 )
  590. {
  591. dwErr = ::RegSetValueEx( *this,
  592. pszValueName,
  593. 0,
  594. REG_BINARY,
  595. pbData,
  596. cbSize ) ;
  597. }
  598. delete pbData ;
  599. return dwErr ;
  600. }
  601. DWORD RegKey::SetValue ( LPCTSTR pszValueName, void * pvResult, DWORD cbSize )
  602. {
  603. DWORD dwErr = 0;
  604. dwErr = ::RegSetValueEx( *this,
  605. pszValueName,
  606. 0,
  607. REG_BINARY,
  608. (const BYTE *)pvResult,
  609. cbSize ) ;
  610. return dwErr ;
  611. }
  612. DWORD RegKey::FlattenValue (
  613. CStringList & strList,
  614. DWORD * pcbSize,
  615. BYTE ** ppbData )
  616. {
  617. return StrList2MULTI_SZ(strList, pcbSize, ppbData);
  618. }
  619. DWORD RegKey::FlattenValue (
  620. CByteArray & abData,
  621. DWORD * pcbSize,
  622. BYTE ** ppbData )
  623. {
  624. DWORD dwErr = 0 ;
  625. DWORD i ;
  626. // Allocate and fill a temporary buffer
  627. if (*pcbSize = (DWORD)abData.GetSize())
  628. {
  629. TRY
  630. {
  631. *ppbData = new BYTE[*pcbSize] ;
  632. for ( i = 0 ; i < *pcbSize ; i++ )
  633. {
  634. (*ppbData)[i] = abData[i] ;
  635. }
  636. }
  637. CATCH_ALL(e)
  638. {
  639. dwErr = ERROR_NOT_ENOUGH_MEMORY ;
  640. }
  641. END_CATCH_ALL
  642. }
  643. else
  644. {
  645. *ppbData = NULL;
  646. }
  647. return dwErr ;
  648. }
  649. DWORD RegKey::QueryKeyInfo ( CREGKEY_KEY_INFO * pRegKeyInfo )
  650. {
  651. DWORD dwErr = 0 ;
  652. pRegKeyInfo->dwClassNameSize = sizeof pRegKeyInfo->chBuff - 1 ;
  653. dwErr = ::RegQueryInfoKey( *this,
  654. pRegKeyInfo->chBuff,
  655. & pRegKeyInfo->dwClassNameSize,
  656. NULL,
  657. & pRegKeyInfo->dwNumSubKeys,
  658. & pRegKeyInfo->dwMaxSubKey,
  659. & pRegKeyInfo->dwMaxClass,
  660. & pRegKeyInfo->dwMaxValues,
  661. & pRegKeyInfo->dwMaxValueName,
  662. & pRegKeyInfo->dwMaxValueData,
  663. & pRegKeyInfo->dwSecDesc,
  664. & pRegKeyInfo->ftKey ) ;
  665. return dwErr ;
  666. }
  667. RegValueIterator::RegValueIterator()
  668. : m_pRegKey( NULL ),
  669. m_pszBuffer( NULL ),
  670. m_cbBuffer( 0 )
  671. {
  672. }
  673. HRESULT RegValueIterator::Init(RegKey *pRegKey)
  674. {
  675. DWORD dwErr = 0 ;
  676. RegKey::CREGKEY_KEY_INFO regKeyInfo ;
  677. Reset() ;
  678. m_pRegKey= pRegKey;
  679. dwErr = pRegKey->QueryKeyInfo( & regKeyInfo ) ;
  680. if ( dwErr == 0 )
  681. {
  682. m_cbBuffer = regKeyInfo.dwMaxValueName + sizeof (DWORD) ;
  683. delete [] m_pszBuffer;
  684. m_pszBuffer = new TCHAR [ m_cbBuffer ] ;
  685. _ASSERTE(m_pszBuffer);
  686. }
  687. return HRESULT_FROM_WIN32(dwErr);
  688. }
  689. RegValueIterator::~RegValueIterator()
  690. {
  691. delete [] m_pszBuffer ;
  692. }
  693. HRESULT RegValueIterator::Next( CString * pstrName, DWORD * pdwType )
  694. {
  695. DWORD dwErr = 0 ;
  696. DWORD dwNameLength = m_cbBuffer ;
  697. dwErr = ::RegEnumValue( *m_pRegKey,
  698. m_dwIndex,
  699. m_pszBuffer,
  700. & dwNameLength,
  701. NULL,
  702. pdwType,
  703. NULL,
  704. NULL ) ;
  705. if ( dwErr == 0 )
  706. {
  707. m_dwIndex++ ;
  708. *pstrName = m_pszBuffer ;
  709. }
  710. return HRESULT_FROM_WIN32(dwErr) ;
  711. }
  712. RegKeyIterator::RegKeyIterator()
  713. : m_pregkey(NULL),
  714. m_pszBuffer(NULL),
  715. m_cbBuffer( 0 )
  716. {
  717. }
  718. HRESULT RegKeyIterator::Init(RegKey *pregkey)
  719. {
  720. DWORD dwErr = 0 ;
  721. RegKey::CREGKEY_KEY_INFO regKeyInfo ;
  722. Reset() ;
  723. m_pregkey= pregkey;
  724. dwErr = pregkey->QueryKeyInfo( & regKeyInfo ) ;
  725. if ( dwErr == 0 )
  726. {
  727. m_cbBuffer = regKeyInfo.dwMaxSubKey + sizeof(DWORD);
  728. delete [] m_pszBuffer;
  729. m_pszBuffer = new TCHAR[m_cbBuffer];
  730. }
  731. return HRESULT_FROM_WIN32(dwErr);
  732. }
  733. RegKeyIterator::~RegKeyIterator ()
  734. {
  735. delete [] m_pszBuffer ;
  736. }
  737. HRESULT RegKeyIterator::Reset()
  738. {
  739. m_dwIndex = 0;
  740. return S_OK;
  741. }
  742. /*!--------------------------------------------------------------------------
  743. RegKeyIterator::Next
  744. Returns the name (and optional last write time) of the next key.
  745. Return S_FALSE if there are no other items to be returned.
  746. Author: KennT
  747. ---------------------------------------------------------------------------*/
  748. HRESULT RegKeyIterator::Next ( CString * pstrName, CTime * pTime )
  749. {
  750. DWORD dwErr = 0;
  751. FILETIME ftDummy ;
  752. DWORD dwNameSize = m_cbBuffer;
  753. dwErr = ::RegEnumKeyEx( *m_pregkey,
  754. m_dwIndex,
  755. m_pszBuffer,
  756. & dwNameSize,
  757. NULL,
  758. NULL,
  759. NULL,
  760. & ftDummy ) ;
  761. if ( dwErr == 0 )
  762. {
  763. m_dwIndex++ ;
  764. if ( pTime )
  765. {
  766. *pTime = ftDummy ;
  767. }
  768. if (pstrName)
  769. {
  770. *pstrName = m_pszBuffer ;
  771. }
  772. }
  773. return (dwErr == ERROR_NO_MORE_ITEMS) ? S_FALSE : HRESULT_FROM_WIN32(dwErr);
  774. }