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.

921 lines
32 KiB

  1. /* /////////////////////////////////////////////////////////////////////////
  2. * File: winstl/registry/reg_value.hpp
  3. *
  4. * Purpose: Contains the basic_reg_value class template, and multibyte
  5. * and wide string specialisations thereof.
  6. *
  7. * Notes: The original implementation of the class had the const_iterator
  8. * and value_type as nested classes. Unfortunately, Visual C++ 5 &
  9. * 6 both had either compilation or linking problems so these are
  10. * regretably now implemented as independent classes.
  11. *
  12. * Created: 19th January 2002
  13. * Updated: 10th August 2009
  14. *
  15. * Thanks: To Diego Chanoux for spotting a defect in the value_sz() method.
  16. *
  17. * To Austin Ziegler for the value_multi_sz() method, and for
  18. * fixes to defects evident on x64.
  19. *
  20. * To Sam Fisher for spotting the defect in the value_sz() and
  21. * value_multi_sz() methods when accessing a zero-size value that
  22. * has one or more non-zero-sized peer values. Ouch!
  23. *
  24. * Home: http://stlsoft.org/
  25. *
  26. * Copyright (c) 2002-2009, Matthew Wilson and Synesis Software
  27. * All rights reserved.
  28. *
  29. * Redistribution and use in source and binary forms, with or without
  30. * modification, are permitted provided that the following conditions are met:
  31. *
  32. * - Redistributions of source code must retain the above copyright notice, this
  33. * list of conditions and the following disclaimer.
  34. * - Redistributions in binary form must reproduce the above copyright notice,
  35. * this list of conditions and the following disclaimer in the documentation
  36. * and/or other materials provided with the distribution.
  37. * - Neither the name(s) of Matthew Wilson and Synesis Software nor the names of
  38. * any contributors may be used to endorse or promote products derived from
  39. * this software without specific prior written permission.
  40. *
  41. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  42. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  43. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  44. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  45. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  46. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  47. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  48. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  49. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  50. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  51. * POSSIBILITY OF SUCH DAMAGE.
  52. *
  53. * ////////////////////////////////////////////////////////////////////// */
  54. /** \file winstl/registry/reg_value.hpp
  55. *
  56. * \brief [C++ only] Definition of the winstl::basic_reg_value class
  57. * template
  58. * (\ref group__library__windows_registry "Windows Registry" Library).
  59. */
  60. #ifndef WINSTL_INCL_WINSTL_REGISTRY_HPP_REG_VALUE
  61. #define WINSTL_INCL_WINSTL_REGISTRY_HPP_REG_VALUE
  62. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  63. # define WINSTL_VER_WINSTL_REGISTRY_HPP_REG_VALUE_MAJOR 3
  64. # define WINSTL_VER_WINSTL_REGISTRY_HPP_REG_VALUE_MINOR 4
  65. # define WINSTL_VER_WINSTL_REGISTRY_HPP_REG_VALUE_REVISION 6
  66. # define WINSTL_VER_WINSTL_REGISTRY_HPP_REG_VALUE_EDIT 107
  67. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  68. /* /////////////////////////////////////////////////////////////////////////
  69. * Includes
  70. */
  71. #ifndef WINSTL_INCL_WINSTL_H_WINSTL
  72. # include <winstl/winstl.h>
  73. #endif /* !WINSTL_INCL_WINSTL_H_WINSTL */
  74. #ifndef WINSTL_INCL_WINSTL_REGISTRY_HPP_REGFWD
  75. # include <winstl/registry/regfwd.hpp>
  76. #endif /* !WINSTL_INCL_WINSTL_REGISTRY_HPP_REGFWD */
  77. #ifndef WINSTL_INCL_WINSTL_REGISTRY_UTIL_HPP_DEFS
  78. # include <winstl/registry/util/defs.hpp>
  79. #endif /* !WINSTL_INCL_WINSTL_REGISTRY_UTIL_HPP_DEFS */
  80. #ifndef WINSTL_INCL_WINSTL_REGISTRY_HPP_REG_TRAITS
  81. # include <winstl/registry/reg_traits.hpp>
  82. #endif /* !WINSTL_INCL_WINSTL_REGISTRY_HPP_REG_TRAITS */
  83. #ifndef WINSTL_INCL_WINSTL_REGISTRY_ERROR_HPP_EXCEPTIONS
  84. # include <winstl/registry/error/exceptions.hpp>
  85. #endif /* !WINSTL_INCL_WINSTL_REGISTRY_ERROR_HPP_EXCEPTIONS */
  86. #ifndef WINSTL_INCL_WINSTL_MEMORY_HPP_PROCESSHEAP_ALLOCATOR
  87. # include <winstl/memory/processheap_allocator.hpp>
  88. #endif /* !WINSTL_INCL_WINSTL_MEMORY_HPP_PROCESSHEAP_ALLOCATOR */
  89. #ifndef STLSOFT_INCL_STLSOFT_MEMORY_HPP_AUTO_BUFFER
  90. # include <stlsoft/memory/auto_buffer.hpp>
  91. #endif /* !STLSOFT_INCL_STLSOFT_MEMORY_HPP_AUTO_BUFFER */
  92. #ifndef STLSOFT_INCL_STLSOFT_UTIL_STD_HPP_ITERATOR_HELPER
  93. # include <stlsoft/util/std/iterator_helper.hpp>
  94. #endif /* !STLSOFT_INCL_STLSOFT_UTIL_STD_HPP_ITERATOR_HELPER */
  95. #ifndef STLSOFT_INCL_STLSOFT_COLLECTIONS_UTIL_HPP_COLLECTIONS
  96. # include <stlsoft/collections/util/collections.hpp>
  97. #endif /* !STLSOFT_INCL_STLSOFT_COLLECTIONS_UTIL_HPP_COLLECTIONS */
  98. #ifndef STLSOFT_INCL_ALGORITHM
  99. # define STLSOFT_INCL_ALGORITHM
  100. # include <algorithm>
  101. #endif /* !STLSOFT_INCL_ALGORITHM */
  102. #ifndef WINSTL_REG_VALUE_NO_MULTI_SZ
  103. # ifndef STLSOFT_INCL_VECTOR
  104. # define STLSOFT_INCL_VECTOR
  105. # include <vector>
  106. # endif /* !STLSOFT_INCL_VECTOR */
  107. #endif /* !WINSTL_REG_VALUE_NO_MULTI_SZ */
  108. #ifndef STLSOFT_UNITTEST
  109. # include <winstl/registry/reg_key.hpp>
  110. #endif /* !STLSOFT_UNITTEST */
  111. /* /////////////////////////////////////////////////////////////////////////
  112. * Namespace
  113. */
  114. #ifndef _WINSTL_NO_NAMESPACE
  115. # if defined(_STLSOFT_NO_NAMESPACE) || \
  116. defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
  117. /* There is no stlsoft namespace, so must define ::winstl */
  118. namespace winstl
  119. {
  120. # else
  121. /* Define stlsoft::winstl_project */
  122. namespace stlsoft
  123. {
  124. namespace winstl_project
  125. {
  126. # endif /* _STLSOFT_NO_NAMESPACE */
  127. #endif /* !_WINSTL_NO_NAMESPACE */
  128. /* ////////////////////////////////////////////////////////////////////// */
  129. /** Represents a binary registry value
  130. *
  131. * \ingroup group__library__windows_registry
  132. */
  133. template<ss_typename_param_k A>
  134. class reg_blob
  135. : protected A
  136. , public stlsoft_ns_qual(stl_collection_tag)
  137. {
  138. /// \name Member Types
  139. /// @{
  140. typedef stlsoft_ns_qual(auto_buffer_old)< ws_byte_t
  141. , processheap_allocator<ws_byte_t>
  142. , CCH_REG_API_AUTO_BUFFER
  143. > buffer_type;
  144. public:
  145. /// The allocator type
  146. typedef A allocator_type;
  147. /// The current parameterisation of the type
  148. typedef reg_blob<A> class_type;
  149. /// The value type
  150. typedef ws_byte_t value_type;
  151. /// The non-mutable (const) reference type
  152. typedef value_type const& const_reference;
  153. /// The non-mutable (const) pointer type
  154. typedef value_type const* const_pointer;
  155. /// The non-mutating (const) iterator type
  156. typedef value_type const* const_iterator;
  157. /// The size type
  158. typedef ws_size_t size_type;
  159. /// The difference type
  160. typedef ws_ptrdiff_t difference_type;
  161. #if defined(STLSOFT_LF_BIDIRECTIONAL_ITERATOR_SUPPORT)
  162. /// The non-mutating (const) reverse iterator type
  163. typedef const_reverse_iterator_base < const_iterator
  164. , value_type const
  165. , const_reference
  166. , const_pointer
  167. , difference_type
  168. > const_reverse_iterator;
  169. #endif /* STLSOFT_LF_BIDIRECTIONAL_ITERATOR_SUPPORT */
  170. /// @}
  171. /// \name Construction
  172. /// @{
  173. public:
  174. /// Default constructor
  175. reg_blob();
  176. /// Copies the contents of the given pointer.
  177. ///
  178. /// \param data Pointer to the bytes to be copied into the instance.
  179. /// \param n Number of bytes pointed to by \c data.
  180. reg_blob(value_type const* data, size_type n);
  181. /// Copy constructor
  182. reg_blob(class_type const& rhs);
  183. /// Destructor
  184. ~reg_blob() stlsoft_throw_0();
  185. /// @}
  186. /// \name Attributes
  187. /// @{
  188. public:
  189. /// Number of bytes in the blob.
  190. size_type size() const;
  191. /// Pointer to the first byte in the blob.
  192. const_pointer data() const;
  193. /// @}
  194. /// \name Iteration
  195. /// @{
  196. public:
  197. /// Begins the iteration
  198. ///
  199. /// \return An iterator representing the start of the sequence
  200. const_iterator begin() const;
  201. /// Ends the iteration
  202. ///
  203. /// \return An iterator representing the end of the sequence
  204. const_iterator end() const;
  205. #if defined(STLSOFT_LF_BIDIRECTIONAL_ITERATOR_SUPPORT)
  206. /// Begins the reverse iteration
  207. ///
  208. /// \return An iterator representing the start of the reverse sequence
  209. const_reverse_iterator rbegin() const;
  210. /// Ends the reverse iteration
  211. ///
  212. /// \return An iterator representing the end of the reverse sequence
  213. const_reverse_iterator rend() const;
  214. #endif /* STLSOFT_LF_BIDIRECTIONAL_ITERATOR_SUPPORT */
  215. /// @}
  216. /// \name Members
  217. /// @{
  218. private:
  219. buffer_type m_buffer;
  220. /// @}
  221. /// \name Not to be implemented
  222. /// @{
  223. private:
  224. reg_blob& operator =(class_type const& rhs);
  225. /// @}
  226. };
  227. /** Represents a registry value, providing methods for accessing the value in different types.
  228. *
  229. * \ingroup group__library__windows_registry
  230. *
  231. * This class acts as the value type of classes that manipulate registry values
  232. * and encapsulates the concept of a registry value.
  233. *
  234. * \param C The character type
  235. * \param T The traits type. On translators that support default template arguments this defaults to reg_traits<C>
  236. * \param A The allocator type. On translators that support default template arguments this defaults to processheap_allocator<C>
  237. */
  238. template< ss_typename_param_k C
  239. #ifdef STLSOFT_CF_TEMPLATE_CLASS_DEFAULT_CLASS_ARGUMENT_SUPPORT
  240. , ss_typename_param_k T = reg_traits<C>
  241. , ss_typename_param_k A = processheap_allocator<C>
  242. #else /* ? STLSOFT_CF_TEMPLATE_CLASS_DEFAULT_CLASS_ARGUMENT_SUPPORT */
  243. , ss_typename_param_k T /* = reg_traits<C> */
  244. , ss_typename_param_k A /* = processheap_allocator<C> */
  245. #endif /* STLSOFT_CF_TEMPLATE_CLASS_DEFAULT_CLASS_ARGUMENT_SUPPORT */
  246. >
  247. class basic_reg_value
  248. {
  249. /// \name Member Types
  250. /// @{
  251. public:
  252. /// The character type
  253. typedef C char_type;
  254. /// The traits type
  255. typedef T traits_type;
  256. /// The allocator type
  257. typedef A allocator_type;
  258. /// The current parameterisation of the type
  259. typedef basic_reg_value<C, T, A> class_type;
  260. /// The size type
  261. typedef ss_typename_type_k traits_type::size_type size_type;
  262. /// The string type
  263. typedef ss_typename_type_k traits_type::string_type string_type;
  264. #ifndef WINSTL_REG_VALUE_NO_MULTI_SZ
  265. /// The string vector type
  266. typedef stlsoft_ns_qual_std(vector)<string_type> strings_type;
  267. #endif /* !WINSTL_REG_VALUE_NO_MULTI_SZ */
  268. /// The key type
  269. #if defined(STLSOFT_CF_THROW_BAD_ALLOC) && \
  270. defined(STLSOFT_COMPILER_IS_MSVC) && \
  271. _MSC_VER == 1100
  272. /* WSCB: VC5 has an internal compiler error if use traits_type::hkey_type */
  273. typedef HKEY hkey_type;
  274. #else /* ? compiler */
  275. typedef ss_typename_type_k traits_type::hkey_type hkey_type;
  276. #endif /* compiler */
  277. /// The blob type
  278. typedef reg_blob<A> blob_type;
  279. private:
  280. typedef stlsoft_ns_qual(auto_buffer_old)< char_type
  281. , allocator_type
  282. , CCH_REG_API_AUTO_BUFFER
  283. > char_buffer_type_;
  284. typedef stlsoft_ns_qual(auto_buffer_old)< ws_byte_t
  285. #ifdef STLSOFT_LF_ALLOCATOR_REBIND_SUPPORT
  286. , ss_typename_type_k allocator_type::ss_template_qual_k rebind<ws_byte_t>::other
  287. #else /* ? STLSOFT_LF_ALLOCATOR_REBIND_SUPPORT */
  288. , processheap_allocator<ws_byte_t>
  289. #endif /* STLSOFT_LF_ALLOCATOR_REBIND_SUPPORT */
  290. , CCH_REG_API_AUTO_BUFFER
  291. > byte_buffer_type_;
  292. private:
  293. /// The results type of the Registry API
  294. typedef ss_typename_type_k traits_type::result_type result_type;
  295. /// @}
  296. /// \name Construction
  297. /// @{
  298. public:
  299. /// Default constructor
  300. basic_reg_value();
  301. /// Copy constructor
  302. basic_reg_value(class_type const& rhs);
  303. protected:
  304. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  305. friend class basic_reg_value_sequence_iterator<C, T, class_type, A>;
  306. friend class basic_reg_key<C, T, A>;
  307. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  308. /// Internal constructor, used by basic_reg_key and basic_reg_value_sequence.
  309. basic_reg_value(hkey_type hkeyParent, string_type const& value_name)
  310. : m_name(value_name)
  311. , m_hkey(dup_key_(hkeyParent, KEY_READ))
  312. , m_type(REG_NONE)
  313. , m_bTypeRetrieved(ws_false_v)
  314. {} // Implementation provided here, as otherwise VC5 will not link
  315. public:
  316. /// Destructor
  317. ~basic_reg_value() stlsoft_throw_0();
  318. /// Copy assignment operator
  319. class_type& operator =(class_type const& rhs);
  320. /// @}
  321. /// \name Attributes
  322. /// @{
  323. public:
  324. /// Returns the type of the value
  325. ///
  326. /// \retval REG_NONE No value type
  327. /// \retval REG_SZ A Unicode nul terminated string
  328. /// \retval REG_EXPAND_SZ A Unicode nul terminated string (with environment variable references)
  329. /// \retval REG_BINARY A free form binary
  330. /// \retval REG_DWORD A 32-bit number
  331. /// \retval REG_DWORD_LITTLE_ENDIAN A little-endian 32-bit number (same as REG_DWORD)
  332. /// \retval REG_DWORD_BIG_ENDIAN A big-endian 32-bit number
  333. /// \retval REG_LINK A symbolic Link (unicode)
  334. /// \retval REG_MULTI_SZ Multiple Unicode strings
  335. /// \retval REG_RESOURCE_LIST A resource list in the resource map
  336. /// \retval REG_FULL_RESOURCE_DESCRIPTOR A resource list in the hardware description
  337. /// \retval REG_RESOURCE_REQUIREMENTS_LIST
  338. /// \retval REG_QWORD A 64-bit number
  339. /// \retval REG_QWORD_LITTLE_ENDIAN A 64-bit number (same as REG_QWORD)
  340. ws_dword_t type() const;
  341. /// The name of the value
  342. string_type name() const;
  343. /// The registry value in \c REG_SZ form
  344. ///
  345. /// This method does <i>not</i> expand environment strings
  346. string_type value_sz() const;
  347. /// The registry value in \c REG_EXPAND_SZ form
  348. ///
  349. /// This method <i>does</i> expand environment strings
  350. string_type value_expand_sz() const;
  351. /// The registry value as a 32-bit integer
  352. ws_dword_t value_dword() const;
  353. /// The registry value as a translated (from little-endian) 32-bit integer
  354. ws_dword_t value_dword_littleendian() const;
  355. /// The registry value as a translated (from big-endian) 32-bit integer
  356. ws_dword_t value_dword_bigendian() const;
  357. /// The registry value as a binary value
  358. blob_type value_binary() const;
  359. #ifndef WINSTL_REG_VALUE_NO_MULTI_SZ
  360. /// The registry value in \c REG_MULTI_SZ form
  361. strings_type value_multi_sz() const;
  362. #endif /* !WINSTL_REG_VALUE_NO_MULTI_SZ */
  363. /// @}
  364. /// \name Implementation
  365. /// @{
  366. private:
  367. ws_dword_t get_type_() const;
  368. static hkey_type dup_key_(hkey_type hkey, REGSAM accessMask/* , result_type *res */);
  369. /// @}
  370. /// \name Members
  371. /// @{
  372. private:
  373. string_type m_name; // The name of the value
  374. hkey_type m_hkey; // The parent key of the value
  375. ss_mutable_k ws_dword_t m_type; // The type of the value
  376. ss_mutable_k ws_bool_t m_bTypeRetrieved; // Facilitates lazy evaluation of the type
  377. /// @}
  378. };
  379. /* Typedefs to commonly encountered types. */
  380. /** Specialisation of the basic_reg_value template for the ANSI character type \c char
  381. *
  382. * \ingroup group__library__windows_registry
  383. */
  384. typedef basic_reg_value<ws_char_a_t, reg_traits<ws_char_a_t>, processheap_allocator<ws_char_a_t> > reg_value_a;
  385. /** Specialisation of the basic_reg_value template for the Unicode character type \c wchar_t
  386. *
  387. * \ingroup group__library__windows_registry
  388. */
  389. typedef basic_reg_value<ws_char_w_t, reg_traits<ws_char_w_t>, processheap_allocator<ws_char_w_t> > reg_value_w;
  390. /** Specialisation of the basic_reg_value template for the Win32 character type \c TCHAR
  391. *
  392. * \ingroup group__library__windows_registry
  393. */
  394. typedef basic_reg_value<TCHAR, reg_traits<TCHAR>, processheap_allocator<TCHAR> > reg_value;
  395. ////////////////////////////////////////////////////////////////////////////
  396. // Unit-testing
  397. #ifdef STLSOFT_UNITTEST
  398. # include "./unittest/reg_value_unittest_.h"
  399. #endif /* STLSOFT_UNITTEST */
  400. /* /////////////////////////////////////////////////////////////////////////
  401. * Implementation
  402. */
  403. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  404. template <ss_typename_param_k C, ss_typename_param_k T, ss_typename_param_k A>
  405. inline basic_reg_value<C, T, A>::basic_reg_value()
  406. : m_name()
  407. , m_hkey(NULL)
  408. , m_type(REG_NONE)
  409. , m_bTypeRetrieved(ws_false_v)
  410. {}
  411. template <ss_typename_param_k C, ss_typename_param_k T, ss_typename_param_k A>
  412. inline basic_reg_value<C, T, A>::basic_reg_value(class_type const& rhs)
  413. : m_name(rhs.m_name)
  414. , m_hkey(dup_key_(rhs.m_hkey, KEY_READ))
  415. , m_type(rhs.m_type)
  416. , m_bTypeRetrieved(rhs.m_bTypeRetrieved)
  417. {}
  418. #if 0
  419. template <ss_typename_param_k C, ss_typename_param_k T, ss_typename_param_k A>
  420. inline basic_reg_value<C, T, A>::basic_reg_value(basic_reg_value<C, T, A>::hkey_type hkeyParent, basic_reg_value<C, T, A>::string_type const& value_name)
  421. : m_name(value_name)
  422. , m_hkey(dup_key_(hkeyParent))
  423. , m_type(REG_NONE)
  424. , m_bTypeRetrieved(ws_false_v)
  425. {}
  426. #endif /* 0 */
  427. template <ss_typename_param_k C, ss_typename_param_k T, ss_typename_param_k A>
  428. inline basic_reg_value<C, T, A>::~basic_reg_value() stlsoft_throw_0()
  429. {
  430. if(m_hkey != NULL)
  431. {
  432. ::RegCloseKey(m_hkey);
  433. }
  434. }
  435. template <ss_typename_param_k C, ss_typename_param_k T, ss_typename_param_k A>
  436. inline ss_typename_type_ret_k basic_reg_value<C, T, A>::class_type& basic_reg_value<C, T, A>::operator =(class_type const& rhs)
  437. {
  438. m_name = rhs.m_name;
  439. m_type = rhs.m_type;
  440. m_bTypeRetrieved = rhs.m_bTypeRetrieved;
  441. hkey_type hkey = m_hkey;
  442. m_hkey = dup_key_(rhs.m_hkey, KEY_READ);
  443. if(hkey != NULL)
  444. {
  445. ::RegCloseKey(hkey);
  446. }
  447. return *this;
  448. }
  449. // Implementation
  450. template <ss_typename_param_k C, ss_typename_param_k T, ss_typename_param_k A>
  451. inline ws_dword_t basic_reg_value<C, T, A>::get_type_() const
  452. {
  453. if(!m_bTypeRetrieved)
  454. {
  455. size_type data_size = 0;
  456. #ifndef STLSOFT_CF_MUTABLE_KEYWORD_SUPPORT
  457. /* A little-known trick, but a useful one for dealing with translators
  458. * lacking mutable support whilst disturbing code to the minimum degree.
  459. */
  460. ws_dword_t &m_type = const_cast<ws_dword_t &>(this->m_type);
  461. ws_bool_t &m_bTypeRetrieved = const_cast<ws_bool_t &>(this->m_bTypeRetrieved);
  462. #endif /* STLSOFT_CF_MUTABLE_KEYWORD_SUPPORT */
  463. if(0 == traits_type::reg_query_value(m_hkey, m_name.c_str(), m_type, NULL, data_size))
  464. {
  465. m_bTypeRetrieved = ws_true_v;
  466. }
  467. }
  468. return m_type;
  469. }
  470. template <ss_typename_param_k C, ss_typename_param_k T, ss_typename_param_k A>
  471. inline /* static */ ss_typename_type_ret_k basic_reg_value<C, T, A>::hkey_type basic_reg_value<C, T, A>::dup_key_(ss_typename_type_k basic_reg_value<C, T, A>::hkey_type hkey, REGSAM accessMask/* , ss_typename_type_k basic_reg_value<C, T, A>::result_type *res */)
  472. {
  473. if(NULL == hkey)
  474. {
  475. return NULL;
  476. }
  477. else
  478. {
  479. result_type res;
  480. HKEY hkeyDup = traits_type::key_dup(hkey, accessMask, &res);
  481. if(ERROR_SUCCESS != res)
  482. {
  483. #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
  484. static const char message[] = "could not duplicate key";
  485. if(ERROR_ACCESS_DENIED == res)
  486. {
  487. STLSOFT_THROW_X(access_denied_exception(message, res));
  488. }
  489. else
  490. {
  491. STLSOFT_THROW_X(key_not_duplicated_exception(message, res));
  492. }
  493. #else /* ? STLSOFT_CF_EXCEPTION_SUPPORT */
  494. ::SetLastError(res);
  495. hkeyDup = NULL;
  496. #endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
  497. }
  498. return hkeyDup;
  499. }
  500. }
  501. // Attributes
  502. template <ss_typename_param_k C, ss_typename_param_k T, ss_typename_param_k A>
  503. inline ws_dword_t basic_reg_value<C, T, A>::type() const
  504. {
  505. return get_type_();
  506. }
  507. template <ss_typename_param_k C, ss_typename_param_k T, ss_typename_param_k A>
  508. inline ss_typename_type_ret_k basic_reg_value<C, T, A>::string_type basic_reg_value<C, T, A>::name() const
  509. {
  510. return m_name;
  511. }
  512. template <ss_typename_param_k C, ss_typename_param_k T, ss_typename_param_k A>
  513. inline ss_typename_type_ret_k basic_reg_value<C, T, A>::string_type basic_reg_value<C, T, A>::value_sz() const
  514. {
  515. // Does not expand environment strings
  516. string_type ret;
  517. size_type data_size = 0;
  518. ws_long_t res = traits_type::reg_query_info(m_hkey, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &data_size, NULL, NULL);
  519. if(ERROR_SUCCESS != res)
  520. {
  521. #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
  522. static const char message[] = "could not determine the data size";
  523. if(ERROR_ACCESS_DENIED == res)
  524. {
  525. STLSOFT_THROW_X(access_denied_exception(message, res));
  526. }
  527. else
  528. {
  529. STLSOFT_THROW_X(registry_exception(message, res));
  530. }
  531. #endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
  532. }
  533. else if(data_size > 0) // Are there _any_ values have non-zero size
  534. {
  535. char_buffer_type_ buffer(1 + data_size);
  536. ws_dword_t dw;
  537. data_size = buffer.size();
  538. res = traits_type::reg_query_value(m_hkey, m_name.c_str(), dw, &buffer[0], data_size);
  539. if(ERROR_SUCCESS != res)
  540. {
  541. #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
  542. static const char message[] = "could not elicit string value";
  543. if(ERROR_ACCESS_DENIED == res)
  544. {
  545. STLSOFT_THROW_X(access_denied_exception(message, res));
  546. }
  547. else
  548. {
  549. STLSOFT_THROW_X(registry_exception(message, res));
  550. }
  551. #endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
  552. }
  553. else if(data_size > 0) // We do a second check here because the requested value might have 0-size, and because registry contents can be changed by other processes
  554. {
  555. WINSTL_ASSERT(0 != data_size);
  556. --data_size; // This is required since the size contains space for the nul-terminator
  557. buffer[data_size / sizeof(char_type)] = 0; // The site of a former bug. Thanks to Diego Chanoux for spotting this
  558. ret.assign(buffer.data(), data_size / sizeof(char_type));
  559. }
  560. }
  561. return ret;
  562. }
  563. template <ss_typename_param_k C, ss_typename_param_k T, ss_typename_param_k A>
  564. inline ss_typename_type_ret_k basic_reg_value<C, T, A>::string_type basic_reg_value<C, T, A>::value_expand_sz() const
  565. {
  566. // Does expand environment strings
  567. string_type ret = value_sz();
  568. if( ret.length() > 0 &&
  569. REG_EXPAND_SZ == get_type_())
  570. {
  571. size_type size = traits_type::expand_environment_strings(ret.c_str(), NULL, 0);
  572. if(0 != size)
  573. {
  574. char_buffer_type_ buffer(1 + size);
  575. if(0 == traits_type::expand_environment_strings(ret.c_str(), &buffer[0], size))
  576. {
  577. #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
  578. static const char message[] = "could not expand environment strings";
  579. DWORD res = ::GetLastError();
  580. if(ERROR_ACCESS_DENIED == res)
  581. {
  582. STLSOFT_THROW_X(access_denied_exception(message, res));
  583. }
  584. else
  585. {
  586. STLSOFT_THROW_X(registry_exception(message, res));
  587. }
  588. #endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
  589. }
  590. else
  591. {
  592. ret.assign(buffer.data(), size);
  593. }
  594. }
  595. }
  596. return ret;
  597. }
  598. template <ss_typename_param_k C, ss_typename_param_k T, ss_typename_param_k A>
  599. inline ws_dword_t basic_reg_value<C, T, A>::value_dword() const
  600. {
  601. ws_dword_t dwValue;
  602. size_type cbData = sizeof(dwValue);
  603. ws_dword_t value_type;
  604. ws_long_t res = traits_type::reg_query_value(m_hkey, m_name.c_str(), value_type, &dwValue, cbData);
  605. if(ERROR_SUCCESS != res)
  606. {
  607. #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
  608. static const char message[] = "could not query value";
  609. if(ERROR_ACCESS_DENIED == res)
  610. {
  611. STLSOFT_THROW_X(access_denied_exception(message, res));
  612. }
  613. else
  614. {
  615. STLSOFT_THROW_X(registry_exception(message, res));
  616. }
  617. #else /* ? STLSOFT_CF_EXCEPTION_SUPPORT */
  618. dwValue = 0;
  619. #endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
  620. }
  621. return dwValue;
  622. }
  623. #if 0
  624. template <ss_typename_param_k C, ss_typename_param_k T, ss_typename_param_k A>
  625. inline ws_dword_t basic_reg_value<C, T, A>::value_dword_littleendian() const
  626. {}
  627. template <ss_typename_param_k C, ss_typename_param_k T, ss_typename_param_k A>
  628. inline ws_dword_t basic_reg_value<C, T, A>::value_dword_bigendian() const
  629. {}
  630. #endif /* 0 */
  631. template <ss_typename_param_k C, ss_typename_param_k T, ss_typename_param_k A>
  632. inline ss_typename_type_ret_k basic_reg_value<C, T, A>::blob_type basic_reg_value<C, T, A>::value_binary() const
  633. {
  634. size_type data_size = 0;
  635. ws_dword_t dw;
  636. ws_long_t res = traits_type::reg_query_value(m_hkey, m_name.c_str(), dw, NULL, data_size);
  637. if(ERROR_SUCCESS != res)
  638. {
  639. #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
  640. query_failed:
  641. static const char message[] = "could not elicit binary value";
  642. if(ERROR_ACCESS_DENIED == res)
  643. {
  644. STLSOFT_THROW_X(access_denied_exception(message, res));
  645. }
  646. else
  647. {
  648. STLSOFT_THROW_X(registry_exception(message, res));
  649. }
  650. #endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
  651. }
  652. else
  653. {
  654. WINSTL_MESSAGE_ASSERT("queried registry value is not binary", dw == REG_BINARY);
  655. if(data_size > 0)
  656. {
  657. byte_buffer_type_ buffer(data_size);
  658. data_size = buffer.size();
  659. res = traits_type::reg_query_value(m_hkey, m_name.c_str(), dw, buffer.data(), data_size);
  660. if(ERROR_SUCCESS != res)
  661. {
  662. #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
  663. goto query_failed;
  664. #endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
  665. }
  666. else
  667. {
  668. return blob_type(buffer.data(), buffer.size());
  669. }
  670. }
  671. }
  672. return blob_type();
  673. }
  674. #ifndef WINSTL_REG_VALUE_NO_MULTI_SZ
  675. template <ss_typename_param_k C, ss_typename_param_k T, ss_typename_param_k A>
  676. inline ss_typename_type_ret_k basic_reg_value<C, T, A>::strings_type basic_reg_value<C, T, A>::value_multi_sz() const
  677. {
  678. strings_type ret;
  679. size_type data_size = 0;
  680. ws_long_t res = traits_type::reg_query_info(m_hkey, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &data_size, NULL, NULL);
  681. if(ERROR_SUCCESS != res)
  682. {
  683. #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
  684. static const char message[] = "could not determine the data size";
  685. if(ERROR_ACCESS_DENIED == res)
  686. {
  687. STLSOFT_THROW_X(access_denied_exception(message, res));
  688. }
  689. else
  690. {
  691. STLSOFT_THROW_X(registry_exception(message, res));
  692. }
  693. #endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
  694. }
  695. else if(data_size > 0) // Are there _any_ values have non-zero size
  696. {
  697. char_buffer_type_ buffer(1 + data_size);
  698. ws_dword_t dw;
  699. data_size = buffer.size();
  700. res = traits_type::reg_query_value(m_hkey, m_name.c_str(), dw, &buffer[0], data_size);
  701. if(ERROR_SUCCESS != res)
  702. {
  703. #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
  704. static const char message[] = "could not elicit string values";
  705. if(ERROR_ACCESS_DENIED == res)
  706. {
  707. STLSOFT_THROW_X(access_denied_exception(message, res));
  708. }
  709. else
  710. {
  711. STLSOFT_THROW_X(registry_exception(message, res));
  712. }
  713. #endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
  714. }
  715. else if(data_size > 0) // We do a second check here because the requested value might have 0-size, and because registry contents can be changed by other processes
  716. {
  717. buffer[data_size / sizeof(char_type)] = 0;
  718. ss_typename_type_k char_buffer_type_::const_iterator start = buffer.begin();
  719. { for(ss_typename_type_k char_buffer_type_::const_iterator ii = buffer.begin(); buffer.end() != ii;)
  720. {
  721. if (*ii != (char_type)0)
  722. {
  723. ++ii;
  724. continue;
  725. }
  726. if ((*ii == (char_type)0) && (*start == (char_type)0))
  727. {
  728. break;
  729. }
  730. ret.push_back(start);
  731. start = ++ii;
  732. }}
  733. if (*start != (char_type)0)
  734. {
  735. ret.push_back(start);
  736. }
  737. }
  738. }
  739. return ret;
  740. }
  741. #endif /* !WINSTL_REG_VALUE_NO_MULTI_SZ */
  742. // reg_blob
  743. template<ss_typename_param_k A>
  744. inline reg_blob<A>::reg_blob()
  745. : m_buffer(0)
  746. {}
  747. template<ss_typename_param_k A>
  748. inline reg_blob<A>::reg_blob(ss_typename_type_k reg_blob<A>::value_type const* data, ss_typename_type_k reg_blob<A>::size_type n)
  749. : m_buffer(n)
  750. {
  751. winstl_ns_qual_std(copy)(data, data + m_buffer.size(), m_buffer.begin());
  752. }
  753. template<ss_typename_param_k A>
  754. inline reg_blob<A>::reg_blob(ss_typename_type_k reg_blob<A>::class_type const& rhs)
  755. : m_buffer(rhs.size())
  756. {
  757. winstl_ns_qual_std(copy)(rhs.data(), rhs.data() + m_buffer.size(), m_buffer.begin());
  758. }
  759. template<ss_typename_param_k A>
  760. inline reg_blob<A>::~reg_blob() stlsoft_throw_0()
  761. {}
  762. template<ss_typename_param_k A>
  763. inline ss_typename_type_ret_k reg_blob<A>::size_type reg_blob<A>::size() const
  764. {
  765. return m_buffer.size();
  766. }
  767. template<ss_typename_param_k A>
  768. inline ss_typename_type_ret_k reg_blob<A>::const_pointer reg_blob<A>::data() const
  769. {
  770. return m_buffer.data();
  771. }
  772. template<ss_typename_param_k A>
  773. inline ss_typename_type_ret_k reg_blob<A>::const_iterator reg_blob<A>::begin() const
  774. {
  775. return m_buffer.begin();
  776. }
  777. template<ss_typename_param_k A>
  778. inline ss_typename_type_ret_k reg_blob<A>::const_iterator reg_blob<A>::end() const
  779. {
  780. return m_buffer.end();
  781. }
  782. #if defined(STLSOFT_LF_BIDIRECTIONAL_ITERATOR_SUPPORT)
  783. template<ss_typename_param_k A>
  784. inline ss_typename_type_ret_k reg_blob<A>::const_reverse_iterator reg_blob<A>::rbegin() const
  785. {
  786. return const_reverse_iterator(end());
  787. }
  788. template<ss_typename_param_k A>
  789. inline ss_typename_type_ret_k reg_blob<A>::const_reverse_iterator reg_blob<A>::rend() const
  790. {
  791. return const_reverse_iterator(begin());
  792. }
  793. #endif /* STLSOFT_LF_BIDIRECTIONAL_ITERATOR_SUPPORT */
  794. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  795. /* ////////////////////////////////////////////////////////////////////// */
  796. #ifndef _WINSTL_NO_NAMESPACE
  797. # if defined(_STLSOFT_NO_NAMESPACE) || \
  798. defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
  799. } // namespace winstl
  800. # else
  801. } // namespace winstl_project
  802. } // namespace stlsoft
  803. # endif /* _STLSOFT_NO_NAMESPACE */
  804. #endif /* !_WINSTL_NO_NAMESPACE */
  805. /* ////////////////////////////////////////////////////////////////////// */
  806. #endif /* WINSTL_INCL_WINSTL_REGISTRY_HPP_REG_VALUE */
  807. /* ///////////////////////////// end of file //////////////////////////// */