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.

1176 lines
38 KiB

  1. ///////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright(C) 1998-1999 Microsoft Corporation all rights reserved.
  4. //
  5. // Module: regpropertybag.cpp
  6. //
  7. // Project: Chameleon
  8. //
  9. // Description: Registry property bag class implementation
  10. //
  11. // Author: TLP
  12. //
  13. // When Who What
  14. // ---- --- ----
  15. // 12/3/98 TLP Original version
  16. // 07/26/99 TLP Updated to support additional types
  17. //
  18. ///////////////////////////////////////////////////////////////////////////
  19. #include "stdafx.h"
  20. #include "regpropertybag.h"
  21. #include <comdef.h>
  22. #include <comutil.h>
  23. #include <varvec.h>
  24. const BYTE abSignature[] = {'#', 'm', 's', '#' };
  25. /////////////////////////////////////////////////
  26. inline void VariantValue(VARIANT* pVar, BYTE* pbVal)
  27. { *pbVal = pVar->bVal; }
  28. inline void VariantValue(BYTE* pbVal, VARIANT* pVar)
  29. { pVar->bVal = *pbVal; }
  30. /////////////////////////////////////////////////
  31. inline void VariantValue(VARIANT* pVar, short* piVal)
  32. { *piVal = pVar->iVal; }
  33. inline void VariantValue(short* piVal, VARIANT* pVar)
  34. { pVar->iVal = *piVal; }
  35. /////////////////////////////////////////////////
  36. inline void VariantValue(VARIANT* pVar, long* plVal)
  37. { *plVal = pVar->lVal; }
  38. inline void VariantValue(long* plVal, VARIANT* pVar)
  39. { pVar->lVal = *plVal; }
  40. /////////////////////////////////////////////////
  41. inline void VariantValue(VARIANT* pVar, float* pfltVal)
  42. { *pfltVal = pVar->fltVal; }
  43. inline void VariantValue(float* pfltVal, VARIANT* pVar)
  44. { pVar->fltVal = *pfltVal; }
  45. /////////////////////////////////////////////////
  46. inline void VariantValue(VARIANT* pVar, double* pdblVal)
  47. { *pdblVal = pVar->dblVal; }
  48. inline void VariantValue(double* pdblVal, VARIANT* pVar)
  49. { pVar->dblVal = *pdblVal; }
  50. /////////////////////////////////////////////////
  51. inline void VariantValue(VARIANT* pVar, CY* pcyVal)
  52. { *pcyVal = pVar->cyVal; }
  53. inline void VariantValue(CY* pcyVal, VARIANT* pVar)
  54. { pVar->cyVal = *pcyVal; }
  55. //////////////////////////////////////////////////////////////////////////////
  56. // Serialize the specified VARIANT into a buffer and persist the buffer
  57. // in a registry key named pszName with type REG_BINARY.
  58. //////////////////////////////////////////////////////////////////////////////
  59. template < class T >
  60. bool saveValue(
  61. /*[in]*/ HKEY hKey,
  62. /*[in]*/ LPCWSTR pszName,
  63. /*[in]*/ VARIANT* pValue,
  64. /*[in]*/ T Size
  65. )
  66. {
  67. bool bRet = false;
  68. try
  69. {
  70. // Determine the size of the buffer needed to
  71. // persist the specified value
  72. PBYTE pBuff = NULL;
  73. DWORD dwBuffSize = sizeof(abSignature) + sizeof(VARTYPE);
  74. VARTYPE vt = V_VT(pValue);
  75. if ( VT_ARRAY < vt )
  76. {
  77. CVariantVector<T> varvec(pValue, vt & ~VT_ARRAY, 0);
  78. dwBuffSize += sizeof(DWORD) + varvec.size() * sizeof(T);
  79. // Create the buffer
  80. pBuff = new BYTE[dwBuffSize];
  81. PBYTE pBuffCur = pBuff;
  82. // Add the parameter header
  83. memcpy(pBuffCur, abSignature, sizeof(abSignature));
  84. pBuffCur += sizeof(abSignature);
  85. *((VARTYPE*)pBuffCur) = vt;
  86. pBuffCur += sizeof(VARTYPE);
  87. // Add the parameter value
  88. *((LPDWORD)pBuffCur) = (DWORD)varvec.size();
  89. pBuffCur += sizeof(DWORD);
  90. memcpy(pBuffCur, varvec.data(), varvec.size() * sizeof(T));
  91. }
  92. else
  93. {
  94. dwBuffSize += sizeof(T);
  95. // Create the buffer
  96. pBuff = new BYTE[dwBuffSize];
  97. PBYTE pBuffCur = pBuff;
  98. // Add the parameter header
  99. memcpy(pBuffCur, abSignature, sizeof(abSignature));
  100. pBuffCur += sizeof(abSignature);
  101. *((VARTYPE*)pBuffCur) = vt;
  102. pBuffCur += sizeof(VARTYPE);
  103. // Add the parameter value
  104. VariantValue(pValue, (T*)pBuffCur);
  105. }
  106. // Save the parameter buffer
  107. if ( ERROR_SUCCESS == RegSetValueEx(
  108. hKey,
  109. pszName,
  110. NULL,
  111. REG_BINARY,
  112. pBuff,
  113. dwBuffSize
  114. ) )
  115. {
  116. bRet = true;
  117. }
  118. delete [] pBuff;
  119. }
  120. catch(...)
  121. {
  122. }
  123. return bRet;
  124. }
  125. //////////////////////////////////////////////////////////////////////////////
  126. template< class T >
  127. void restoreValue(
  128. PBYTE pBuff,
  129. VARIANT* pValue,
  130. T Size
  131. )
  132. {
  133. pBuff += sizeof(abSignature);
  134. VARTYPE vt = *((VARTYPE*)pBuff);
  135. pBuff += sizeof(VARTYPE);
  136. if ( VT_ARRAY < vt )
  137. {
  138. DWORD dwElements = *((LPDWORD)pBuff);
  139. pBuff += sizeof(DWORD);
  140. CVariantVector<T> varvec(pValue, vt & ~VT_ARRAY, dwElements);
  141. memcpy(varvec.data(), pBuff, dwElements * sizeof(T));
  142. }
  143. else
  144. {
  145. VariantValue((T*)pBuff, pValue);
  146. }
  147. V_VT(pValue) = vt;
  148. }
  149. /////////////////////////////////////////////////////////////////////////
  150. // CRegPropertyBag - Implementation of CPropertyBag
  151. /////////////////////////////////////////////////////////////////////////
  152. CRegPropertyBag::CRegPropertyBag(CLocationInfo& locationInfo)
  153. : m_isContainer(false),
  154. m_maxPropertyName(0),
  155. m_locationInfo(locationInfo)
  156. {
  157. m_name = m_locationInfo.getShortName();
  158. }
  159. /////////////////////////////////////////////////////////////////////////
  160. CRegPropertyBag::~CRegPropertyBag()
  161. {
  162. close();
  163. releaseProperties();
  164. }
  165. //////////////////////////////////////////////////////////////////////////
  166. bool
  167. CRegPropertyBag::open()
  168. {
  169. try
  170. {
  171. close();
  172. LONG lReturn = m_key.Open(
  173. (HKEY)m_locationInfo.getHandle(),
  174. m_locationInfo.getName(),
  175. KEY_ALL_ACCESS
  176. );
  177. if ( ERROR_SUCCESS == lReturn )
  178. {
  179. if ( load() )
  180. return true;
  181. }
  182. // DoTrace("");
  183. }
  184. catch(...)
  185. {
  186. // DoTrace("");
  187. }
  188. m_key.m_hKey = NULL;
  189. return false;
  190. }
  191. //////////////////////////////////////////////////////////////////////////
  192. void
  193. CRegPropertyBag::close()
  194. {
  195. if ( getKey() )
  196. m_key.Close();
  197. }
  198. //////////////////////////////////////////////////////////////////////////
  199. void
  200. CRegPropertyBag::getLocation(CLocationInfo& locationInfo)
  201. {
  202. locationInfo = m_locationInfo;
  203. }
  204. //////////////////////////////////////////////////////////////////////////
  205. bool
  206. CRegPropertyBag::load()
  207. {
  208. if ( getKey() )
  209. {
  210. bool bOK;
  211. CRegInfo regInfo(bOK, (HKEY)m_key);
  212. if ( bOK )
  213. {
  214. LONG lReturn = ERROR_SUCCESS;
  215. DWORD dwIndex = 0;
  216. DWORD dwMaxValueName;
  217. DWORD dwType;
  218. DWORD dwMaxValueData;
  219. DWORD dwValue;
  220. VARTYPE vt;
  221. releaseProperties();
  222. try
  223. {
  224. _variant_t vtValue;
  225. while ( dwIndex < regInfo.m_dwValues )
  226. {
  227. dwMaxValueName = regInfo.m_dwMaxValueName;
  228. lReturn = RegEnumValue(
  229. getKey(),
  230. dwIndex,
  231. regInfo.m_pValueName,
  232. &dwMaxValueName,
  233. NULL,
  234. &dwType,
  235. NULL,
  236. NULL
  237. );
  238. if ( ERROR_SUCCESS != lReturn )
  239. {
  240. // DoTrace("");
  241. throw CRegError();
  242. }
  243. switch( dwType )
  244. {
  245. ///////////////
  246. case REG_DWORD:
  247. lReturn = m_key.QueryValue(dwValue, regInfo.m_pValueName);
  248. if ( ERROR_SUCCESS != lReturn )
  249. {
  250. // DoTrace("");
  251. throw CRegError();
  252. }
  253. vtValue = (long)dwValue;
  254. break;
  255. ///////////////////
  256. case REG_EXPAND_SZ: // Note we do not expand the string here...
  257. case REG_SZ:
  258. dwMaxValueData = regInfo.m_dwMaxValueData;
  259. lReturn = m_key.QueryValue((LPTSTR)regInfo.m_pValueData, regInfo.m_pValueName, &dwMaxValueData);
  260. if ( ERROR_SUCCESS != lReturn )
  261. {
  262. // DoTrace("");
  263. throw CRegError();
  264. }
  265. vtValue = (LPCWSTR)regInfo.m_pValueData;
  266. break;
  267. ////////////////
  268. case REG_BINARY:
  269. dwMaxValueData = regInfo.m_dwMaxValueData;
  270. lReturn = RegQueryValueEx(
  271. getKey(),
  272. regInfo.m_pValueName,
  273. NULL,
  274. &dwType,
  275. regInfo.m_pValueData,
  276. &dwMaxValueData
  277. );
  278. if ( ERROR_SUCCESS != lReturn )
  279. {
  280. // DoTrace("");
  281. throw CRegError();
  282. }
  283. vt = getTypeFromBuffer(dwMaxValueData, regInfo.m_pValueData);
  284. switch ( vt & ~VT_ARRAY )
  285. {
  286. ///////////
  287. case VT_UI1:
  288. {
  289. BYTE size = sizeof(BYTE);
  290. restoreValue(regInfo.m_pValueData, &vtValue, size);
  291. }
  292. break;
  293. ///////////
  294. case VT_I2:
  295. {
  296. short size = sizeof(short);
  297. restoreValue(regInfo.m_pValueData, &vtValue, size);
  298. }
  299. break;
  300. case VT_BOOL:
  301. {
  302. VARIANT_BOOL size = sizeof(VARIANT_BOOL);
  303. restoreValue(regInfo.m_pValueData, &vtValue, size);
  304. }
  305. break;
  306. ///////////
  307. case VT_R4:
  308. {
  309. float size = sizeof(float);
  310. restoreValue(regInfo.m_pValueData, &vtValue, size);
  311. }
  312. break;
  313. ///////////
  314. case VT_R8:
  315. {
  316. double size = sizeof(double);
  317. restoreValue(regInfo.m_pValueData, &vtValue, size);
  318. }
  319. break;
  320. ///////////
  321. case VT_CY:
  322. {
  323. CY size = { sizeof(CY), sizeof(CY) };
  324. restoreValue(regInfo.m_pValueData, &vtValue, size);
  325. }
  326. break;
  327. ///////////
  328. case VT_DATE:
  329. {
  330. DATE size = sizeof(DATE);
  331. restoreValue(regInfo.m_pValueData, &vtValue, size);
  332. }
  333. break;
  334. ///////////
  335. case VT_ERROR:
  336. {
  337. SCODE size = sizeof(SCODE);
  338. restoreValue(regInfo.m_pValueData, &vtValue, size);
  339. }
  340. break;
  341. ///////////
  342. case VT_I4:
  343. case VT_BSTR:
  344. _ASSERT(FALSE);
  345. // DoTrace("");
  346. throw CRegError();
  347. break;
  348. default:
  349. CVariantVector<unsigned char> theBuff(&vtValue, dwMaxValueData);
  350. break;
  351. }
  352. break;
  353. //////////////////
  354. case REG_MULTI_SZ:
  355. {
  356. dwMaxValueData = regInfo.m_dwMaxValueData;
  357. lReturn = m_key.QueryValue((LPTSTR)regInfo.m_pValueData, regInfo.m_pValueName, &dwMaxValueData);
  358. if ( ERROR_SUCCESS != lReturn )
  359. {
  360. // DoTrace("");
  361. throw CRegError();
  362. }
  363. // Determine number of strings
  364. DWORD dwStrs = 0;
  365. LPWSTR pszStr = (LPWSTR)regInfo.m_pValueData;
  366. while ( *pszStr )
  367. {
  368. dwStrs++;
  369. pszStr += lstrlen(pszStr) + 1;
  370. }
  371. // Create a VARIANT of BSTRs for the strings
  372. if ( dwStrs )
  373. {
  374. CVariantVector<BSTR> theStrings(&vtValue, dwStrs);
  375. pszStr = (LPWSTR)regInfo.m_pValueData;
  376. for ( int i = 0; i < dwStrs; i++ )
  377. {
  378. theStrings[i] = SysAllocString(pszStr);
  379. pszStr += lstrlen(pszStr) + 1;
  380. }
  381. }
  382. else
  383. {
  384. CVariantVector<BSTR> theStrings(&vtValue, 1);
  385. theStrings[0] = SysAllocString(L"");
  386. }
  387. }
  388. break;
  389. ////////
  390. default:
  391. // DoTrace("Unsupported Type");
  392. throw CRegError();
  393. break;
  394. }
  395. // Create new propertyinfo object then add it to the collection
  396. pair<PropertyMapIterator, bool> thePair = m_properties.insert(PropertyMap::value_type(regInfo.m_pValueName, vtValue));
  397. if ( false == thePair.second )
  398. {
  399. // DoTrace("");
  400. throw CRegError();
  401. }
  402. dwIndex++;
  403. }
  404. if ( regInfo.m_dwSubKeys )
  405. {
  406. m_isContainer = true;
  407. }
  408. m_maxPropertyName = regInfo.m_dwMaxValueName;
  409. reset();
  410. return true;
  411. }
  412. catch(...)
  413. {
  414. releaseProperties();
  415. }
  416. }
  417. }
  418. return false;
  419. }
  420. //////////////////////////////////////////////////////////////////////////
  421. bool
  422. CRegPropertyBag::save()
  423. {
  424. if ( getKey() )
  425. {
  426. try
  427. {
  428. LONG lReturn;
  429. PropertyMapIterator p = m_properties.begin();
  430. while ( p != m_properties.end() )
  431. {
  432. VARTYPE vt = V_VT(&((*p).second));
  433. switch ( vt & ~ VT_ARRAY )
  434. {
  435. /////////////
  436. case VT_BSTR:
  437. if ( VT_ARRAY < vt )
  438. {
  439. // Format the safe array of BSTRs
  440. // into a REG_MULTI_SZ
  441. DWORD dwBuffSize = 0;
  442. int i = 0;
  443. CVariantVector<BSTR> theArray(&((*p).second));
  444. for ( i = 0; i < theArray.size(); i++ )
  445. {
  446. dwBuffSize += (lstrlen(theArray[i]) + 1) * sizeof(WCHAR);
  447. }
  448. dwBuffSize += sizeof(WCHAR); // terminated by 2 NULL characters
  449. PBYTE pBuff = new BYTE[dwBuffSize];
  450. PBYTE pBuffCur = pBuff;
  451. memset(pBuff, 0, dwBuffSize);
  452. for ( i = 0; i < theArray.size(); i++ )
  453. {
  454. lstrcpy((LPWSTR)pBuffCur, theArray[i]);
  455. pBuffCur += (lstrlen(theArray[i]) + 1) * sizeof(WCHAR);
  456. }
  457. if ( ERROR_SUCCESS != RegSetValueEx(
  458. getKey(),
  459. (*p).first.c_str(),
  460. NULL,
  461. REG_MULTI_SZ,
  462. pBuff,
  463. dwBuffSize
  464. ) )
  465. {
  466. // DoTrace("");
  467. throw CRegError();
  468. }
  469. delete[] pBuff;
  470. }
  471. else
  472. {
  473. // Single string value
  474. if ( ERROR_SUCCESS != m_key.SetValue(V_BSTR(&((*p).second)), (*p).first.c_str()) )
  475. {
  476. // DoTrace("");
  477. throw CRegError();
  478. }
  479. }
  480. break;
  481. ///////////
  482. case VT_I4:
  483. if ( ERROR_SUCCESS != m_key.SetValue((DWORD)V_I4(&((*p).second)), (*p).first.c_str()) )
  484. {
  485. // DoTrace("");
  486. throw CRegError();
  487. }
  488. break;
  489. ////////////
  490. case VT_UI1:
  491. {
  492. BYTE size = sizeof(BYTE);
  493. if ( ! saveValue(getKey(), (*p).first.c_str(), &((*p).second), size) )
  494. {
  495. // DoTrace("");
  496. throw CRegError();
  497. }
  498. }
  499. break;
  500. ///////////
  501. case VT_I2:
  502. {
  503. short size = sizeof(short);
  504. if ( ! saveValue(getKey(), (*p).first.c_str(), &((*p).second), size) )
  505. {
  506. // DoTrace("");
  507. throw CRegError();
  508. }
  509. }
  510. break;
  511. case VT_BOOL:
  512. {
  513. VARIANT_BOOL size = sizeof(VARIANT_BOOL);
  514. if ( ! saveValue(getKey(), (*p).first.c_str(), &((*p).second), size) )
  515. {
  516. // DoTrace("");
  517. throw CRegError();
  518. }
  519. }
  520. break;
  521. ///////////
  522. case VT_R4:
  523. {
  524. float size = sizeof(float);
  525. if ( ! saveValue(getKey(), (*p).first.c_str(), &((*p).second), size) )
  526. {
  527. // DoTrace("");
  528. throw CRegError();
  529. }
  530. }
  531. break;
  532. ///////////
  533. case VT_R8:
  534. {
  535. double size = sizeof(double);
  536. if ( ! saveValue(getKey(), (*p).first.c_str(), &((*p).second), size) )
  537. {
  538. // DoTrace("");
  539. throw CRegError();
  540. }
  541. }
  542. break;
  543. ///////////
  544. case VT_CY:
  545. {
  546. CY size = { sizeof(CY), sizeof(CY) };
  547. if ( ! saveValue(getKey(), (*p).first.c_str(), &((*p).second), size) )
  548. {
  549. // DoTrace("");
  550. throw CRegError();
  551. }
  552. }
  553. break;
  554. ///////////
  555. case VT_DATE:
  556. {
  557. DATE size = sizeof(DATE);
  558. if ( ! saveValue(getKey(), (*p).first.c_str(), &((*p).second), size) )
  559. {
  560. // DoTrace("");
  561. throw CRegError();
  562. }
  563. }
  564. break;
  565. ///////////
  566. case VT_ERROR:
  567. {
  568. SCODE size = sizeof(SCODE);
  569. if ( ! saveValue(getKey(), (*p).first.c_str(), &((*p).second), size) )
  570. {
  571. // DoTrace("");
  572. throw CRegError();
  573. }
  574. }
  575. break;
  576. ////////
  577. default:
  578. _ASSERT( FALSE );
  579. // DoTrace("");
  580. throw CRegError();
  581. break;
  582. }
  583. p++;
  584. }
  585. return true;
  586. }
  587. catch(...)
  588. {
  589. }
  590. }
  591. return false;
  592. }
  593. //////////////////////////////////////////////////////////////////////////
  594. bool
  595. CRegPropertyBag::IsContainer(void)
  596. {
  597. return m_isContainer;
  598. }
  599. //////////////////////////////////////////////////////////////////////////
  600. PPROPERTYBAGCONTAINER
  601. CRegPropertyBag::getContainer()
  602. {
  603. if ( m_isContainer )
  604. return ::MakePropertyBagContainer(PROPERTY_BAG_REGISTRY, m_locationInfo);
  605. return PPROPERTYBAGCONTAINER();
  606. }
  607. //////////////////////////////////////////////////////////////////////////
  608. LPCWSTR
  609. CRegPropertyBag::getName(void)
  610. {
  611. return m_name.c_str();
  612. }
  613. //////////////////////////////////////////////////////////////////////////
  614. DWORD
  615. CRegPropertyBag::getMaxPropertyName(void)
  616. {
  617. return m_maxPropertyName;
  618. }
  619. //////////////////////////////////////////////////////////////////////////
  620. bool
  621. CRegPropertyBag::IsProperty(LPCWSTR pszPropertyName)
  622. {
  623. _ASSERT( pszPropertyName );
  624. PropertyMapIterator p = MyFind(pszPropertyName);
  625. if ( p != m_properties.end() )
  626. {
  627. return true;
  628. }
  629. return false;
  630. }
  631. //////////////////////////////////////////////////////////////////////////
  632. bool
  633. CRegPropertyBag::get(LPCWSTR pszPropertyName, VARIANT* pValue)
  634. {
  635. _ASSERT( pszPropertyName );
  636. PropertyMapIterator p = MyFind(pszPropertyName);
  637. if ( p != m_properties.end() )
  638. {
  639. if ( SUCCEEDED(VariantCopy(pValue, &((*p).second))) )
  640. {
  641. return true;
  642. }
  643. }
  644. // DoTrace("");
  645. return false;
  646. }
  647. //////////////////////////////////////////////////////////////////////////
  648. bool
  649. CRegPropertyBag::put(LPCWSTR pszPropertyName, VARIANT* pValue)
  650. {
  651. _ASSERT( pszPropertyName );
  652. if ( ! IsSupportedType(V_VT(pValue)) )
  653. {
  654. return false;
  655. }
  656. // Try to locate the specified property...
  657. PropertyMapIterator p = MyFind(pszPropertyName);
  658. if ( p != m_properties.end() )
  659. {
  660. // Existing property. We're either changing its value or removing it.
  661. if ( VT_EMPTY == V_VT(pValue) )
  662. {
  663. // Removing it
  664. if ( m_current == p )
  665. {
  666. m_current = m_properties.erase(p);
  667. }
  668. else
  669. {
  670. m_properties.erase(p);
  671. }
  672. }
  673. else
  674. {
  675. // Changing its value (and possibly its type)
  676. if ( SUCCEEDED(VariantCopy(&((*p).second), pValue)) )
  677. {
  678. return true;
  679. }
  680. }
  681. }
  682. else
  683. {
  684. if ( VT_EMPTY != V_VT(pValue) )
  685. {
  686. // New property. Insert it into the property map
  687. pair<PropertyMapIterator, bool> thePair = m_properties.insert(PropertyMap::value_type(pszPropertyName, pValue));
  688. if ( false == thePair.second )
  689. {
  690. // DoTrace("");
  691. throw CRegError();
  692. }
  693. int length = lstrlen(pszPropertyName);
  694. if ( length > m_maxPropertyName )
  695. {
  696. m_maxPropertyName = length;
  697. }
  698. }
  699. return true;
  700. }
  701. // DoTrace("");
  702. return false;
  703. }
  704. //////////////////////////////////////////////////////////////////////////
  705. bool
  706. CRegPropertyBag::current(LPWSTR pszPropertyName, VARIANT* pValue)
  707. {
  708. if ( ! m_properties.empty() )
  709. {
  710. lstrcpy(pszPropertyName, ((*m_current).first).c_str());
  711. if ( SUCCEEDED(VariantCopy(pValue, &(*m_current).second)) )
  712. {
  713. return true;
  714. }
  715. }
  716. // DoTrace("");
  717. return false;
  718. }
  719. //////////////////////////////////////////////////////////////////////////
  720. bool
  721. CRegPropertyBag::reset()
  722. {
  723. m_current = m_properties.begin();
  724. return true;
  725. }
  726. //////////////////////////////////////////////////////////////////////////
  727. bool
  728. CRegPropertyBag::next()
  729. {
  730. if ( ! m_properties.empty() )
  731. {
  732. m_current++;
  733. if ( m_current == m_properties.end() )
  734. {
  735. m_current--;
  736. }
  737. else
  738. {
  739. return true;
  740. }
  741. }
  742. // DoTrace("");
  743. return false;
  744. }
  745. //////////////////////////////////////
  746. // CRegPropertyBag - private functions
  747. //////////////////////////////////////////////////////////////////////////////
  748. VARTYPE
  749. CRegPropertyBag::getTypeFromBuffer(
  750. /*[in]*/ DWORD dwBuffSize,
  751. /*[in]*/ PBYTE pBuff
  752. )
  753. {
  754. VARTYPE vt = VT_EMPTY;
  755. if ( dwBuffSize > sizeof(abSignature) + sizeof(VARTYPE) )
  756. {
  757. if ( ! memcmp(pBuff, abSignature, sizeof(abSignature)) )
  758. {
  759. pBuff += sizeof(abSignature);
  760. vt = *((VARTYPE*)pBuff);
  761. if ( ! IsSupportedType(vt) )
  762. {
  763. vt = VT_EMPTY;
  764. }
  765. }
  766. }
  767. return vt;
  768. }
  769. //////////////////////////////////////////////////////////////////////////
  770. PropertyMapIterator
  771. CRegPropertyBag::MyFind(LPCWSTR pszPropertyName)
  772. {
  773. PropertyMapIterator p = m_properties.begin();
  774. while ( p != m_properties.end() )
  775. {
  776. if ( ! lstrcmpi(pszPropertyName, (*p).first.c_str()) )
  777. {
  778. break;
  779. }
  780. p++;
  781. }
  782. return p;
  783. }
  784. //////////////////////////////////////////////////////////////////////////
  785. bool
  786. CRegPropertyBag::IsSupportedType(VARTYPE vt)
  787. {
  788. bool bRet = false;
  789. switch ( vt & ~ VT_ARRAY )
  790. {
  791. case VT_UI1:
  792. case VT_I2:
  793. case VT_BOOL:
  794. case VT_I4:
  795. case VT_R4:
  796. case VT_R8:
  797. case VT_CY:
  798. case VT_DATE:
  799. case VT_ERROR:
  800. case VT_BSTR:
  801. case VT_UNKNOWN: // Allow put() and get() of COM objects
  802. case VT_DISPATCH:
  803. case VT_EMPTY: // Used to erase an existing bag value
  804. bRet = true;
  805. break;
  806. default:
  807. break;
  808. };
  809. return bRet;
  810. }
  811. //////////////////////////////////////////////////////////////////////////
  812. void
  813. CRegPropertyBag::releaseProperties()
  814. {
  815. PropertyMapIterator p = m_properties.begin();
  816. while ( p != m_properties.end() )
  817. p = m_properties.erase(p);
  818. }
  819. //////////////////////////////////////////////////////////////////////////
  820. // CRegPropertyBagContainer
  821. //////////////////////////////////////////////////////////////////////////
  822. //////////////////////////////////////////////////////////////////////////
  823. CRegPropertyBagContainer::CRegPropertyBagContainer(CLocationInfo& locationInfo)
  824. : m_locationInfo(locationInfo)
  825. {
  826. m_name = m_locationInfo.getShortName();
  827. }
  828. //////////////////////////////////////////////////////////////////////////
  829. CRegPropertyBagContainer::~CRegPropertyBagContainer()
  830. {
  831. close();
  832. releaseBags();
  833. }
  834. //////////////////////////////////////////////////////////////////////////
  835. bool
  836. CRegPropertyBagContainer::open()
  837. {
  838. close();
  839. try
  840. {
  841. LONG lReturn = m_key.Open(
  842. (HKEY)m_locationInfo.getHandle(),
  843. m_locationInfo.getName(),
  844. KEY_ALL_ACCESS
  845. );
  846. if ( ERROR_SUCCESS == lReturn )
  847. {
  848. bool bOk;
  849. CRegInfo regInfo(bOk, getKey());
  850. if ( bOk )
  851. {
  852. LONG lResult = ERROR_SUCCESS;
  853. DWORD dwKeyNameSize;
  854. FILETIME sFileTime;
  855. DWORD dwIndex = 0;
  856. releaseBags();
  857. while ( lResult == ERROR_SUCCESS )
  858. {
  859. dwKeyNameSize = regInfo.m_dwMaxSubKeyName;
  860. lResult = RegEnumKeyEx(
  861. getKey(),
  862. dwIndex,
  863. regInfo.m_pSubKeyName,
  864. &dwKeyNameSize,
  865. NULL,
  866. NULL,
  867. NULL,
  868. &sFileTime
  869. );
  870. if ( ERROR_SUCCESS == lResult )
  871. {
  872. PPROPERTYBAG pBag = addBag(regInfo.m_pSubKeyName);
  873. if ( ! pBag.IsValid() )
  874. throw CRegError();
  875. }
  876. dwIndex++;
  877. }
  878. if ( ERROR_NO_MORE_ITEMS == lResult )
  879. return true;
  880. }
  881. }
  882. }
  883. catch(...)
  884. {
  885. close();
  886. releaseBags();
  887. }
  888. // DoTrace("");
  889. return false;
  890. }
  891. //////////////////////////////////////////////////////////////////////////
  892. void
  893. CRegPropertyBagContainer::close()
  894. {
  895. if ( getKey() )
  896. m_key.Close();
  897. }
  898. //////////////////////////////////////////////////////////////////////////
  899. void
  900. CRegPropertyBagContainer::getLocation(CLocationInfo& locationInfo)
  901. {
  902. locationInfo = m_locationInfo;
  903. }
  904. //////////////////////////////////////////////////////////////////////////
  905. LPCWSTR
  906. CRegPropertyBagContainer::getName()
  907. {
  908. return m_name.c_str();
  909. }
  910. //////////////////////////////////////////////////////////////////////////
  911. DWORD
  912. CRegPropertyBagContainer::count(void)
  913. {
  914. return m_bags.size();
  915. }
  916. //////////////////////////////////////////////////////////////////////////
  917. PPROPERTYBAG
  918. CRegPropertyBagContainer::add(LPCWSTR pszName)
  919. {
  920. try
  921. {
  922. if ( getKey() )
  923. {
  924. HKEY hKey;
  925. DWORD dwDisposition;
  926. LONG lRes = RegCreateKeyEx(
  927. getKey(),
  928. pszName,
  929. 0,
  930. REG_NONE,
  931. REG_OPTION_NON_VOLATILE,
  932. KEY_ALL_ACCESS,
  933. NULL,
  934. &hKey,
  935. &dwDisposition
  936. );
  937. if ( ERROR_SUCCESS == lRes)
  938. {
  939. CLocationInfo locationBag(getKey(), pszName);
  940. PPROPERTYBAG pBag = ::MakePropertyBag(PROPERTY_BAG_REGISTRY, locationBag);
  941. pair<BagMapIterator, bool> thePair = m_bags.insert(BagMap::value_type(pszName, pBag));
  942. if ( true == thePair.second )
  943. {
  944. RegCloseKey(hKey);
  945. return pBag;
  946. }
  947. else
  948. { m_key.DeleteSubKey(pszName); }
  949. }
  950. }
  951. }
  952. catch(...)
  953. {
  954. }
  955. // DoTrace("");
  956. return PPROPERTYBAG();
  957. }
  958. //////////////////////////////////////////////////////////////////////////
  959. bool
  960. CRegPropertyBagContainer::remove(LPCWSTR pszName)
  961. {
  962. if ( getKey() )
  963. {
  964. BagMapIterator p = m_bags.find(pszName);
  965. if ( p != m_bags.end() )
  966. {
  967. if ( m_current == p )
  968. m_current = m_bags.erase(p);
  969. else
  970. m_bags.erase(p);
  971. if ( ERROR_SUCCESS == m_key.DeleteSubKey(pszName) )
  972. return true;
  973. }
  974. }
  975. // DoTrace("");
  976. return false;
  977. }
  978. //////////////////////////////////////////////////////////////////////////
  979. PPROPERTYBAG
  980. CRegPropertyBagContainer::find(LPCWSTR pszName)
  981. {
  982. if ( getKey() )
  983. {
  984. BagMapIterator p = m_bags.begin();
  985. while ( p != m_bags.end() )
  986. {
  987. if ( ! lstrcmpi(pszName, (*p).first.c_str()) )
  988. {
  989. return (*p).second;
  990. }
  991. p++;
  992. }
  993. }
  994. // DoTrace("")
  995. return PPROPERTYBAG();
  996. }
  997. //////////////////////////////////////////////////////////////////////////
  998. PPROPERTYBAG
  999. CRegPropertyBagContainer::current()
  1000. {
  1001. if ( getKey() )
  1002. {
  1003. if ( ! m_bags.empty() )
  1004. return (*m_current).second;
  1005. }
  1006. // DoTrace("");
  1007. return PPROPERTYBAG();
  1008. }
  1009. //////////////////////////////////////////////////////////////////////////
  1010. bool
  1011. CRegPropertyBagContainer::reset()
  1012. {
  1013. if ( getKey() )
  1014. {
  1015. m_current = m_bags.begin();
  1016. return true;
  1017. }
  1018. // DoTrace("")
  1019. return false;
  1020. }
  1021. //////////////////////////////////////////////////////////////////////////
  1022. bool
  1023. CRegPropertyBagContainer::next()
  1024. {
  1025. if ( getKey() )
  1026. {
  1027. if ( ! m_bags.empty() )
  1028. {
  1029. m_current++;
  1030. if ( m_current == m_bags.end() )
  1031. m_current--;
  1032. else
  1033. return true;
  1034. }
  1035. }
  1036. // DoTrace("");
  1037. return false;
  1038. }
  1039. //////////////////////////////////////////////////////////////////////////
  1040. PPROPERTYBAG
  1041. CRegPropertyBagContainer::addBag(LPCWSTR pszName)
  1042. {
  1043. try
  1044. {
  1045. wstring szObjName = m_locationInfo.getName();
  1046. szObjName += L"\\";
  1047. szObjName += pszName;
  1048. CLocationInfo locationBag(m_locationInfo.getHandle(), szObjName.c_str());
  1049. PPROPERTYBAG pBag = ::MakePropertyBag(PROPERTY_BAG_REGISTRY, locationBag);
  1050. pair<BagMapIterator, bool> thePair = m_bags.insert(BagMap::value_type(pszName, pBag));
  1051. if ( true == thePair.second )
  1052. { return pBag; }
  1053. }
  1054. catch(...)
  1055. {
  1056. }
  1057. // DoTrace("");
  1058. return PPROPERTYBAG();
  1059. }
  1060. //////////////////////////////////////////////////////////////////////////
  1061. void
  1062. CRegPropertyBagContainer::releaseBags()
  1063. {
  1064. BagMapIterator p = m_bags.begin();
  1065. while ( p != m_bags.end() )
  1066. p = m_bags.erase(p);
  1067. }