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.

795 lines
14 KiB

  1. #include "stdafx.h"
  2. #include <stdlib.h>
  3. #include <memory.h>
  4. #include <ctype.h>
  5. #include "registry.h"
  6. #ifdef _DEBUG
  7. #undef THIS_FILE
  8. static char BASED_CODE THIS_FILE[] = __FILE__;
  9. #endif
  10. CRegKey::CRegKey (
  11. HKEY hKeyBase,
  12. LPCTSTR pchSubKey,
  13. REGSAM regSam,
  14. LPCTSTR pchServerName
  15. )
  16. : m_hKey(NULL),
  17. m_dwDisposition(0)
  18. {
  19. HKEY hkBase = NULL ;
  20. LONG err = ERROR_SUCCESS;
  21. if ( pchServerName != NULL)
  22. {
  23. //
  24. // This is a remote connection.
  25. //
  26. err = ::RegConnectRegistry((LPTSTR)pchServerName, hKeyBase, &hkBase);
  27. if (err != ERROR_SUCCESS)
  28. {
  29. hkBase = NULL ;
  30. }
  31. // hkBase == NULL ;
  32. }
  33. else
  34. {
  35. hkBase = hKeyBase ;
  36. }
  37. if (err == ERROR_SUCCESS)
  38. {
  39. if ( pchSubKey )
  40. {
  41. err = ::RegOpenKeyEx( hkBase, pchSubKey, 0, regSam, & m_hKey ) ;
  42. }
  43. else
  44. {
  45. m_hKey = hkBase ;
  46. hkBase = NULL ;
  47. }
  48. if ( hkBase && hkBase != hKeyBase )
  49. {
  50. ::RegCloseKey( hkBase ) ;
  51. }
  52. }
  53. if ( err != ERROR_SUCCESS)
  54. {
  55. m_hKey = NULL ;
  56. }
  57. }
  58. //
  59. // Constructor creating a new key.
  60. //
  61. CRegKey::CRegKey (
  62. LPCTSTR pchSubKey,
  63. HKEY hKeyBase,
  64. DWORD dwOptions,
  65. REGSAM regSam,
  66. LPSECURITY_ATTRIBUTES pSecAttr,
  67. LPCTSTR pchServerName
  68. )
  69. : m_hKey(NULL),
  70. m_dwDisposition(0)
  71. {
  72. HKEY hkBase = NULL ;
  73. LONG err = 0;
  74. if (pchServerName != NULL)
  75. {
  76. //
  77. // This is a remote connection.
  78. //
  79. err = ::RegConnectRegistry((LPTSTR)pchServerName, hKeyBase, & hkBase);
  80. if (err != ERROR_SUCCESS)
  81. {
  82. hkBase = NULL;
  83. }
  84. // hkBase == NULL;
  85. }
  86. else
  87. {
  88. hkBase = hKeyBase ;
  89. }
  90. if (err == ERROR_SUCCESS)
  91. {
  92. LPCTSTR szEmpty = _T("") ;
  93. err = ::RegCreateKeyEx( hkBase, pchSubKey, 0, (TCHAR *) szEmpty,
  94. dwOptions, regSam, pSecAttr, &m_hKey, &m_dwDisposition );
  95. }
  96. if (err != ERROR_SUCCESS)
  97. {
  98. m_hKey = NULL ;
  99. }
  100. }
  101. CRegKey::~CRegKey()
  102. {
  103. if (m_hKey != NULL)
  104. {
  105. ::RegCloseKey( m_hKey ) ;
  106. }
  107. }
  108. //
  109. // Prepare to read a value by finding the value's size.
  110. //
  111. LONG
  112. CRegKey :: PrepareValue (
  113. LPCTSTR pchValueName,
  114. DWORD * pdwType,
  115. DWORD * pcbSize,
  116. BYTE ** ppbData
  117. )
  118. {
  119. LONG err = 0 ;
  120. BYTE chDummy[2] ;
  121. DWORD cbData = 0 ;
  122. do
  123. {
  124. //
  125. // Set the resulting buffer size to 0.
  126. //
  127. *pcbSize = 0 ;
  128. *ppbData = NULL ;
  129. err = ::RegQueryValueEx(*this, (LPTSTR) pchValueName,
  130. 0, pdwType, chDummy, &cbData);
  131. //
  132. // The only error we should get here is ERROR_MORE_DATA, but
  133. // we may get no error if the value has no data.
  134. //
  135. if (err == ERROR_SUCCESS)
  136. {
  137. cbData = sizeof(LONG); // Just a fudgy number
  138. }
  139. else
  140. {
  141. if ( err != ERROR_MORE_DATA )
  142. {
  143. break;
  144. }
  145. }
  146. //
  147. // Allocate a buffer large enough for the data.
  148. //
  149. *ppbData = new BYTE [ (*pcbSize = cbData) + sizeof (LONG) ] ;
  150. if ( *ppbData == NULL )
  151. {
  152. err = ERROR_NOT_ENOUGH_MEMORY ;
  153. break ;
  154. }
  155. //
  156. // Now that have a buffer, re-fetch the value.
  157. //
  158. err = ::RegQueryValueEx( *this, (LPTSTR)pchValueName,
  159. 0, pdwType, *ppbData, pcbSize );
  160. } while (FALSE);
  161. if (err != ERROR_SUCCESS)
  162. {
  163. delete [] *ppbData;
  164. }
  165. return err;
  166. }
  167. //
  168. // Overloaded value query members; each returns ERROR_INVALID_PARAMETER
  169. // if data exists but not in correct form to deliver into result object.
  170. //
  171. LONG
  172. CRegKey::QueryValue (
  173. const TCHAR * pchValueName,
  174. CString &strResult
  175. )
  176. {
  177. LONG err = 0;
  178. DWORD dwType;
  179. DWORD cbData;
  180. BYTE * pabData = NULL;
  181. do
  182. {
  183. if ( err = PrepareValue( pchValueName, & dwType, & cbData, & pabData ) )
  184. {
  185. break;
  186. }
  187. if ( dwType != REG_SZ )
  188. {
  189. err = ERROR_INVALID_PARAMETER ;
  190. break ;
  191. }
  192. //
  193. // Guarantee that the data looks like a string
  194. //
  195. pabData[cbData] = 0 ;
  196. //
  197. // Catch exceptions trying to assign to the caller's string
  198. //
  199. TRY
  200. {
  201. strResult = (TCHAR *) pabData ;
  202. }
  203. CATCH_ALL(e)
  204. {
  205. err = ERROR_NOT_ENOUGH_MEMORY ;
  206. }
  207. END_CATCH_ALL
  208. }
  209. while (FALSE);
  210. delete [] pabData ;
  211. return err ;
  212. }
  213. LONG
  214. CRegKey::QueryValue (
  215. LPCTSTR pchValueName,
  216. CStringList &strList
  217. )
  218. {
  219. LONG err = 0;
  220. DWORD dwType;
  221. DWORD cbData;
  222. BYTE * pabData = NULL;
  223. LPTSTR pbTemp, pbTempLimit;
  224. do
  225. {
  226. if ( err = PrepareValue( pchValueName, & dwType, & cbData, & pabData ))
  227. {
  228. break;
  229. }
  230. if ( dwType != REG_MULTI_SZ )
  231. {
  232. err = ERROR_INVALID_PARAMETER ;
  233. break ;
  234. }
  235. //
  236. // Guarantee that the trailing data looks like a string
  237. //
  238. pabData[cbData] = 0 ;
  239. pbTemp = (TCHAR *) pabData ;
  240. pbTempLimit = & pbTemp[cbData] ;
  241. //
  242. // Catch exceptions trying to build the list
  243. //
  244. TRY
  245. {
  246. for ( /**/ ; pbTemp < pbTempLimit ; /**/ )
  247. {
  248. strList.AddTail( pbTemp ) ;
  249. pbTemp += ::_tcslen( pbTemp ) + sizeof(TCHAR) ;
  250. }
  251. }
  252. CATCH_ALL(e)
  253. {
  254. err = ERROR_NOT_ENOUGH_MEMORY ;
  255. }
  256. END_CATCH_ALL
  257. }
  258. while ( FALSE );
  259. delete [] pabData ;
  260. return err;
  261. }
  262. LONG
  263. CRegKey :: QueryValue (
  264. LPCTSTR pchValueName,
  265. DWORD &dwResult
  266. )
  267. {
  268. LONG err = 0 ;
  269. DWORD dwType ;
  270. DWORD cbData ;
  271. BYTE * pabData = NULL ;
  272. do
  273. {
  274. if ( err = PrepareValue( pchValueName, & dwType, & cbData, & pabData ) )
  275. {
  276. break ;
  277. }
  278. if ( dwType != REG_DWORD || cbData != sizeof dwResult )
  279. {
  280. err = ERROR_INVALID_PARAMETER ;
  281. break ;
  282. }
  283. dwResult = *((DWORD *) pabData) ;
  284. }
  285. while ( FALSE ) ;
  286. delete [] pabData ;
  287. return err ;
  288. }
  289. LONG
  290. CRegKey :: QueryValue (
  291. LPCTSTR pchValueName,
  292. CByteArray &abResult
  293. )
  294. {
  295. LONG err = 0 ;
  296. DWORD dwType ;
  297. DWORD cbData ;
  298. BYTE * pabData = NULL ;
  299. do
  300. {
  301. if ( err = PrepareValue( pchValueName, & dwType, & cbData, & pabData ) )
  302. {
  303. break ;
  304. }
  305. if ( dwType != REG_BINARY )
  306. {
  307. err = ERROR_INVALID_PARAMETER ;
  308. break ;
  309. }
  310. //
  311. // Catch exceptions trying to grow the result array
  312. //
  313. TRY
  314. {
  315. abResult.SetSize( cbData ) ;
  316. }
  317. CATCH_ALL(e)
  318. {
  319. err = ERROR_NOT_ENOUGH_MEMORY ;
  320. }
  321. END_CATCH_ALL
  322. if ( err != ERROR_SUCCESS)
  323. {
  324. break ;
  325. }
  326. //
  327. // Move the data to the result array.
  328. //
  329. for ( DWORD i = 0 ; i < cbData ; ++i )
  330. {
  331. abResult[i] = pabData[i] ;
  332. }
  333. }
  334. while ( FALSE ) ;
  335. delete [] pabData ;
  336. return err ;
  337. }
  338. LONG
  339. CRegKey::QueryValue (
  340. LPCTSTR pchValueName,
  341. void * pvResult,
  342. DWORD cbSize
  343. )
  344. {
  345. LONG err = 0 ;
  346. DWORD dwType ;
  347. DWORD cbData ;
  348. BYTE * pabData = NULL ;
  349. do
  350. {
  351. if ( err = PrepareValue( pchValueName, & dwType, & cbData, & pabData ) )
  352. {
  353. break;
  354. }
  355. if ( dwType != REG_BINARY )
  356. {
  357. err = ERROR_INVALID_PARAMETER ;
  358. break ;
  359. }
  360. if ( cbSize < cbData )
  361. {
  362. err = ERROR_MORE_DATA;
  363. break;
  364. }
  365. ::memcpy(pvResult, pabData, cbData);
  366. }
  367. while ( FALSE ) ;
  368. delete [] pabData ;
  369. return err ;
  370. }
  371. //
  372. // Overloaded value setting members.
  373. //
  374. LONG
  375. CRegKey::SetValue (
  376. LPCTSTR pchValueName,
  377. CString & strResult
  378. )
  379. {
  380. return ::RegSetValueEx( *this, pchValueName, 0, REG_SZ,
  381. (const BYTE *) (const TCHAR *) strResult, strResult.GetLength() + 1 );
  382. }
  383. LONG
  384. CRegKey :: SetValue (
  385. LPCTSTR pchValueName,
  386. CStringList & strList
  387. )
  388. {
  389. LONG err = 0;
  390. DWORD cbSize ;
  391. BYTE * pbData = NULL ;
  392. err = FlattenValue( strList, & cbSize, & pbData ) ;
  393. if ( err == ERROR_SUCCESS )
  394. {
  395. err = ::RegSetValueEx(*this, pchValueName, 0, REG_MULTI_SZ, pbData, cbSize);
  396. }
  397. delete pbData ;
  398. return err ;
  399. }
  400. LONG
  401. CRegKey::SetValue (
  402. LPCTSTR pchValueName,
  403. DWORD &dwResult
  404. )
  405. {
  406. return ::RegSetValueEx(*this, pchValueName, 0, REG_DWORD,
  407. (const BYTE *) & dwResult, sizeof dwResult);
  408. }
  409. LONG
  410. CRegKey::SetValue (
  411. LPCTSTR pchValueName,
  412. CByteArray & abResult
  413. )
  414. {
  415. LONG err = 0;
  416. DWORD cbSize ;
  417. BYTE * pbData = NULL ;
  418. err = FlattenValue(abResult, &cbSize, &pbData);
  419. if (err == ERROR_SUCCESS)
  420. {
  421. err = ::RegSetValueEx(*this, pchValueName,
  422. 0,REG_BINARY, pbData, cbSize);
  423. }
  424. delete pbData;
  425. return err;
  426. }
  427. LONG
  428. CRegKey::SetValue (
  429. LPCTSTR pchValueName,
  430. void * pvResult,
  431. DWORD cbSize
  432. )
  433. {
  434. return ::RegSetValueEx( *this, pchValueName,
  435. 0, REG_BINARY, (const BYTE *)pvResult, cbSize );
  436. }
  437. LONG
  438. CRegKey::DeleteValue (
  439. LPCTSTR pchValueName
  440. )
  441. {
  442. return ::RegDeleteValue( *this, (LPTSTR) pchValueName);
  443. }
  444. LONG
  445. CRegKey::FlattenValue (
  446. CStringList & strList,
  447. DWORD * pcbSize,
  448. BYTE ** ppbData
  449. )
  450. {
  451. LONG err = 0 ;
  452. POSITION pos ;
  453. CString * pstr ;
  454. int cbTotal = 0 ;
  455. //
  456. // Walk the list accumulating sizes
  457. //
  458. for (pos = strList.GetHeadPosition();
  459. pos != NULL && (pstr = & strList.GetNext( pos )) ; /**/ )
  460. {
  461. cbTotal += pstr->GetLength() + 1;
  462. }
  463. //
  464. // Allocate and fill a temporary buffer
  465. //
  466. if (*pcbSize = cbTotal)
  467. {
  468. TRY
  469. {
  470. *ppbData = new BYTE[ *pcbSize ] ;
  471. BYTE * pbData = *ppbData ;
  472. //
  473. // Populate the buffer with the strings.
  474. //
  475. for (pos = strList.GetHeadPosition();
  476. pos != NULL && (pstr = & strList.GetNext( pos )) ; /**/ )
  477. {
  478. int cb = pstr->GetLength() + 1 ;
  479. ::memcpy( pbData, (LPCTSTR) *pstr, cb );
  480. pbData += cb ;
  481. }
  482. }
  483. CATCH_ALL(e)
  484. {
  485. err = ERROR_NOT_ENOUGH_MEMORY ;
  486. }
  487. END_CATCH_ALL
  488. }
  489. else
  490. {
  491. *ppbData = NULL;
  492. }
  493. return err ;
  494. }
  495. LONG
  496. CRegKey::FlattenValue(
  497. CByteArray & abData,
  498. DWORD * pcbSize,
  499. BYTE ** ppbData
  500. )
  501. {
  502. LONG err = 0 ;
  503. DWORD i ;
  504. //
  505. // Allocate and fill a temporary buffer
  506. //
  507. if (*pcbSize = (DWORD)abData.GetSize())
  508. {
  509. TRY
  510. {
  511. *ppbData = new BYTE[*pcbSize] ;
  512. for ( i = 0 ; i < *pcbSize ; i++ )
  513. {
  514. (*ppbData)[i] = abData[i] ;
  515. }
  516. }
  517. CATCH_ALL(e)
  518. {
  519. err = ERROR_NOT_ENOUGH_MEMORY ;
  520. }
  521. END_CATCH_ALL
  522. }
  523. else
  524. {
  525. *ppbData = NULL;
  526. }
  527. return err;
  528. }
  529. LONG
  530. CRegKey::QueryKeyInfo (
  531. CREGKEY_KEY_INFO * pRegKeyInfo
  532. )
  533. {
  534. LONG err = 0 ;
  535. pRegKeyInfo->dwClassNameSize = sizeof pRegKeyInfo->chBuff - 1 ;
  536. err = ::RegQueryInfoKey(*this,
  537. pRegKeyInfo->chBuff,
  538. &pRegKeyInfo->dwClassNameSize,
  539. NULL,
  540. &pRegKeyInfo->dwNumSubKeys,
  541. &pRegKeyInfo->dwMaxSubKey,
  542. &pRegKeyInfo->dwMaxClass,
  543. &pRegKeyInfo->dwMaxValues,
  544. &pRegKeyInfo->dwMaxValueName,
  545. &pRegKeyInfo->dwMaxValueData,
  546. &pRegKeyInfo->dwSecDesc,
  547. &pRegKeyInfo->ftKey
  548. );
  549. return err ;
  550. }
  551. //
  552. // Iteration class
  553. //
  554. CRegKeyIter::CRegKeyIter (
  555. CRegKey & regKey
  556. )
  557. : m_rk_iter( regKey ),
  558. m_p_buffer( NULL ),
  559. m_cb_buffer( 0 )
  560. {
  561. LONG err = 0 ;
  562. CRegKey::CREGKEY_KEY_INFO regKeyInfo ;
  563. Reset() ;
  564. err = regKey.QueryKeyInfo( & regKeyInfo ) ;
  565. if ( err == 0 )
  566. {
  567. TRY
  568. {
  569. m_cb_buffer = regKeyInfo.dwMaxSubKey + sizeof (DWORD) ;
  570. m_p_buffer = new TCHAR [ m_cb_buffer ] ;
  571. }
  572. CATCH_ALL(e)
  573. {
  574. err = ERROR_NOT_ENOUGH_MEMORY ;
  575. }
  576. END_CATCH_ALL
  577. }
  578. }
  579. CRegKeyIter :: ~ CRegKeyIter ()
  580. {
  581. delete [] m_p_buffer ;
  582. }
  583. //
  584. // Get the name (and optional last write time) of the next key.
  585. //
  586. LONG CRegKeyIter::Next(
  587. CString * pstrName,
  588. CTime * pTime
  589. )
  590. {
  591. LONG err = 0;
  592. FILETIME ftDummy ;
  593. DWORD dwNameSize = m_cb_buffer ;
  594. err = ::RegEnumKeyEx( m_rk_iter, m_dw_index, m_p_buffer, & dwNameSize,
  595. NULL, NULL, NULL, & ftDummy ) ;
  596. if (err == ERROR_SUCCESS)
  597. {
  598. ++m_dw_index;
  599. if ( pTime )
  600. {
  601. *pTime = ftDummy ;
  602. }
  603. TRY
  604. {
  605. *pstrName = m_p_buffer ;
  606. }
  607. CATCH_ALL(e)
  608. {
  609. err = ERROR_NOT_ENOUGH_MEMORY ;
  610. }
  611. END_CATCH_ALL
  612. }
  613. return err;
  614. }
  615. CRegValueIter::CRegValueIter (
  616. CRegKey &regKey
  617. )
  618. : m_rk_iter(regKey),
  619. m_p_buffer(NULL),
  620. m_cb_buffer(0)
  621. {
  622. LONG err = 0;
  623. CRegKey::CREGKEY_KEY_INFO regKeyInfo ;
  624. Reset() ;
  625. err = regKey.QueryKeyInfo( & regKeyInfo ) ;
  626. if (err == ERROR_SUCCESS)
  627. {
  628. TRY
  629. {
  630. m_cb_buffer = regKeyInfo.dwMaxValueName + sizeof (DWORD);
  631. m_p_buffer = new TCHAR [ m_cb_buffer ] ;
  632. }
  633. CATCH_ALL(e)
  634. {
  635. err = ERROR_NOT_ENOUGH_MEMORY ;
  636. }
  637. END_CATCH_ALL
  638. }
  639. }
  640. CRegValueIter::~ CRegValueIter()
  641. {
  642. delete [] m_p_buffer;
  643. }
  644. LONG
  645. CRegValueIter::Next (
  646. CString * pstrName,
  647. DWORD * pdwType
  648. )
  649. {
  650. LONG err = 0 ;
  651. DWORD dwNameLength = m_cb_buffer ;
  652. err = ::RegEnumValue(m_rk_iter, m_dw_index, m_p_buffer,
  653. &dwNameLength, NULL, pdwType, NULL, NULL );
  654. if ( err == ERROR_SUCCESS )
  655. {
  656. ++m_dw_index;
  657. TRY
  658. {
  659. *pstrName = m_p_buffer;
  660. }
  661. CATCH_ALL(e)
  662. {
  663. err = ERROR_NOT_ENOUGH_MEMORY ;
  664. }
  665. END_CATCH_ALL
  666. }
  667. return err;
  668. }