winstl/registry/reg_value.hpp

Go to the documentation of this file.
00001 /* /////////////////////////////////////////////////////////////////////////
00002  * File:        winstl/registry/reg_value.hpp
00003  *
00004  * Purpose:     Contains the basic_reg_value class template, and multibyte
00005  *              and wide string specialisations thereof.
00006  *
00007  * Notes:       The original implementation of the class had the const_iterator
00008  *              and value_type as nested classes. Unfortunately, Visual C++ 5 &
00009  *              6 both had either compilation or linking problems so these are
00010  *              regretably now implemented as independent classes.
00011  *
00012  * Created:     19th January 2002
00013  * Updated:     10th August 2009
00014  *
00015  * Thanks:      To Diego Chanoux for spotting a defect in the value_sz() method.
00016  *
00017  *              To Austin Ziegler for the value_multi_sz() method, and for
00018  *              fixes to defects evident on x64.
00019  *
00020  *              To Sam Fisher for spotting the defect in the value_sz() and
00021  *              value_multi_sz() methods when accessing a zero-size value that
00022  *              has one or more non-zero-sized peer values. Ouch!
00023  *
00024  * Home:        http://stlsoft.org/
00025  *
00026  * Copyright (c) 2002-2009, Matthew Wilson and Synesis Software
00027  * All rights reserved.
00028  *
00029  * Redistribution and use in source and binary forms, with or without
00030  * modification, are permitted provided that the following conditions are met:
00031  *
00032  * - Redistributions of source code must retain the above copyright notice, this
00033  *   list of conditions and the following disclaimer.
00034  * - Redistributions in binary form must reproduce the above copyright notice,
00035  *   this list of conditions and the following disclaimer in the documentation
00036  *   and/or other materials provided with the distribution.
00037  * - Neither the name(s) of Matthew Wilson and Synesis Software nor the names of
00038  *   any contributors may be used to endorse or promote products derived from
00039  *   this software without specific prior written permission.
00040  *
00041  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00042  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00043  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00044  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00045  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00046  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00047  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00048  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00049  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00050  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00051  * POSSIBILITY OF SUCH DAMAGE.
00052  *
00053  * ////////////////////////////////////////////////////////////////////// */
00054 
00055 
00063 #ifndef WINSTL_INCL_WINSTL_REGISTRY_HPP_REG_VALUE
00064 #define WINSTL_INCL_WINSTL_REGISTRY_HPP_REG_VALUE
00065 
00066 #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
00067 # define WINSTL_VER_WINSTL_REGISTRY_HPP_REG_VALUE_MAJOR     3
00068 # define WINSTL_VER_WINSTL_REGISTRY_HPP_REG_VALUE_MINOR     4
00069 # define WINSTL_VER_WINSTL_REGISTRY_HPP_REG_VALUE_REVISION  6
00070 # define WINSTL_VER_WINSTL_REGISTRY_HPP_REG_VALUE_EDIT      107
00071 #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
00072 
00073 /* /////////////////////////////////////////////////////////////////////////
00074  * Includes
00075  */
00076 
00077 #ifndef WINSTL_INCL_WINSTL_H_WINSTL
00078 # include <winstl/winstl.h>
00079 #endif /* !WINSTL_INCL_WINSTL_H_WINSTL */
00080 #ifndef WINSTL_INCL_WINSTL_REGISTRY_HPP_REGFWD
00081 # include <winstl/registry/regfwd.hpp>
00082 #endif /* !WINSTL_INCL_WINSTL_REGISTRY_HPP_REGFWD */
00083 #ifndef WINSTL_INCL_WINSTL_REGISTRY_UTIL_HPP_DEFS
00084 # include <winstl/registry/util/defs.hpp>
00085 #endif /* !WINSTL_INCL_WINSTL_REGISTRY_UTIL_HPP_DEFS */
00086 #ifndef WINSTL_INCL_WINSTL_REGISTRY_HPP_REG_TRAITS
00087 # include <winstl/registry/reg_traits.hpp>
00088 #endif /* !WINSTL_INCL_WINSTL_REGISTRY_HPP_REG_TRAITS */
00089 #ifndef WINSTL_INCL_WINSTL_REGISTRY_ERROR_HPP_EXCEPTIONS
00090 # include <winstl/registry/error/exceptions.hpp>
00091 #endif /* !WINSTL_INCL_WINSTL_REGISTRY_ERROR_HPP_EXCEPTIONS */
00092 #ifndef WINSTL_INCL_WINSTL_MEMORY_HPP_PROCESSHEAP_ALLOCATOR
00093 # include <winstl/memory/processheap_allocator.hpp>
00094 #endif /* !WINSTL_INCL_WINSTL_MEMORY_HPP_PROCESSHEAP_ALLOCATOR */
00095 #ifndef STLSOFT_INCL_STLSOFT_MEMORY_HPP_AUTO_BUFFER
00096 # include <stlsoft/memory/auto_buffer.hpp>
00097 #endif /* !STLSOFT_INCL_STLSOFT_MEMORY_HPP_AUTO_BUFFER */
00098 #ifndef STLSOFT_INCL_STLSOFT_UTIL_STD_HPP_ITERATOR_HELPER
00099 # include <stlsoft/util/std/iterator_helper.hpp>
00100 #endif /* !STLSOFT_INCL_STLSOFT_UTIL_STD_HPP_ITERATOR_HELPER */
00101 #ifndef STLSOFT_INCL_STLSOFT_COLLECTIONS_UTIL_HPP_COLLECTIONS
00102 # include <stlsoft/collections/util/collections.hpp>
00103 #endif /* !STLSOFT_INCL_STLSOFT_COLLECTIONS_UTIL_HPP_COLLECTIONS */
00104 
00105 #ifndef STLSOFT_INCL_ALGORITHM
00106 # define STLSOFT_INCL_ALGORITHM
00107 # include <algorithm>
00108 #endif /* !STLSOFT_INCL_ALGORITHM */
00109 #ifndef WINSTL_REG_VALUE_NO_MULTI_SZ
00110 # ifndef STLSOFT_INCL_VECTOR
00111 #  define STLSOFT_INCL_VECTOR
00112 #  include <vector>
00113 # endif /* !STLSOFT_INCL_VECTOR */
00114 #endif /* !WINSTL_REG_VALUE_NO_MULTI_SZ */
00115 
00116 #ifndef STLSOFT_UNITTEST
00117 # include <winstl/registry/reg_key.hpp>
00118 #endif /* !STLSOFT_UNITTEST */
00119 
00120 /* /////////////////////////////////////////////////////////////////////////
00121  * Namespace
00122  */
00123 
00124 #ifndef _WINSTL_NO_NAMESPACE
00125 # if defined(_STLSOFT_NO_NAMESPACE) || \
00126      defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
00127 /* There is no stlsoft namespace, so must define ::winstl */
00128 namespace winstl
00129 {
00130 # else
00131 /* Define stlsoft::winstl_project */
00132 
00133 namespace stlsoft
00134 {
00135 
00136 namespace winstl_project
00137 {
00138 
00139 # endif /* _STLSOFT_NO_NAMESPACE */
00140 #endif /* !_WINSTL_NO_NAMESPACE */
00141 
00142 /* ////////////////////////////////////////////////////////////////////// */
00143 
00148 template<ss_typename_param_k A>
00149 class reg_blob
00150     : protected A
00151     , public stlsoft_ns_qual(stl_collection_tag)
00152 {
00155     typedef stlsoft_ns_qual(auto_buffer_old)<   ws_byte_t
00156                                             ,   processheap_allocator<ws_byte_t>
00157                                             ,   CCH_REG_API_AUTO_BUFFER
00158                                             >               buffer_type;
00159 public:
00161     typedef A                                               allocator_type;
00163     typedef reg_blob<A>                                     class_type;
00165     typedef ws_byte_t                                       value_type;
00167     typedef value_type const&                               const_reference;
00169     typedef value_type const*                               const_pointer;
00171     typedef value_type const*                               const_iterator;
00173     typedef ws_size_t                                       size_type;
00175     typedef ws_ptrdiff_t                                    difference_type;
00176 #if defined(STLSOFT_LF_BIDIRECTIONAL_ITERATOR_SUPPORT)
00178     typedef const_reverse_iterator_base <   const_iterator
00179                                         ,   value_type const
00180                                         ,   const_reference
00181                                         ,   const_pointer
00182                                         ,   difference_type
00183                                         >                   const_reverse_iterator;
00184 #endif /* STLSOFT_LF_BIDIRECTIONAL_ITERATOR_SUPPORT */
00186 
00189 public:
00191     reg_blob();
00196     reg_blob(value_type const* data, size_type n);
00198     reg_blob(class_type const& rhs);
00200     ~reg_blob() stlsoft_throw_0();
00202 
00205 public:
00207     size_type       size() const;
00209     const_pointer   data() const;
00211 
00214 public:
00218     const_iterator  begin() const;
00222     const_iterator  end() const;
00223 
00224 #if defined(STLSOFT_LF_BIDIRECTIONAL_ITERATOR_SUPPORT)
00228     const_reverse_iterator  rbegin() const;
00232     const_reverse_iterator  rend() const;
00233 #endif /* STLSOFT_LF_BIDIRECTIONAL_ITERATOR_SUPPORT */
00235 
00238 private:
00239     buffer_type m_buffer;
00241 
00244 private:
00245     reg_blob& operator =(class_type const& rhs);
00247 };
00248 
00260 template<   ss_typename_param_k C
00261 #ifdef STLSOFT_CF_TEMPLATE_CLASS_DEFAULT_CLASS_ARGUMENT_SUPPORT
00262         ,   ss_typename_param_k T = reg_traits<C>
00263         ,   ss_typename_param_k A = processheap_allocator<C>
00264 #else /* ? STLSOFT_CF_TEMPLATE_CLASS_DEFAULT_CLASS_ARGUMENT_SUPPORT */
00265         ,   ss_typename_param_k T /* = reg_traits<C> */
00266         ,   ss_typename_param_k A /* = processheap_allocator<C> */
00267 #endif /* STLSOFT_CF_TEMPLATE_CLASS_DEFAULT_CLASS_ARGUMENT_SUPPORT */
00268         >
00269 class basic_reg_value
00270 {
00273 public:
00275     typedef C                                                           char_type;
00277     typedef T                                                           traits_type;
00279     typedef A                                                           allocator_type;
00281     typedef basic_reg_value<C, T, A>                                    class_type;
00283     typedef ss_typename_type_k traits_type::size_type                   size_type;
00285     typedef ss_typename_type_k traits_type::string_type                 string_type;
00286 #ifndef WINSTL_REG_VALUE_NO_MULTI_SZ
00288     typedef stlsoft_ns_qual_std(vector)<string_type>                    strings_type;
00289 #endif /* !WINSTL_REG_VALUE_NO_MULTI_SZ */
00291 #if defined(STLSOFT_CF_THROW_BAD_ALLOC) && \
00292     defined(STLSOFT_COMPILER_IS_MSVC) && \
00293     _MSC_VER == 1100
00294     /* WSCB: VC5 has an internal compiler error if use traits_type::hkey_type */
00295     typedef HKEY                                                        hkey_type;
00296 #else /* ? compiler */
00297     typedef ss_typename_type_k traits_type::hkey_type                   hkey_type;
00298 #endif /* compiler */
00300     typedef reg_blob<A>                                                 blob_type;
00301 private:
00302     typedef stlsoft_ns_qual(auto_buffer_old)<   char_type
00303                                             ,   allocator_type
00304                                             ,   CCH_REG_API_AUTO_BUFFER
00305                                             >                           char_buffer_type_;
00306     typedef stlsoft_ns_qual(auto_buffer_old)<   ws_byte_t
00307 #ifdef STLSOFT_LF_ALLOCATOR_REBIND_SUPPORT
00308                                             ,   ss_typename_type_k allocator_type::ss_template_qual_k rebind<ws_byte_t>::other
00309 #else /* ? STLSOFT_LF_ALLOCATOR_REBIND_SUPPORT */
00310                                             ,   processheap_allocator<ws_byte_t>
00311 #endif /* STLSOFT_LF_ALLOCATOR_REBIND_SUPPORT */
00312                                             ,   CCH_REG_API_AUTO_BUFFER
00313                                             >                           byte_buffer_type_;
00314 private:
00316     typedef ss_typename_type_k traits_type::result_type                 result_type;
00318 
00321 public:
00323     basic_reg_value();
00325     basic_reg_value(class_type const& rhs);
00326 protected:
00327 #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
00328     friend class basic_reg_value_sequence_iterator<C, T, class_type, A>;
00329     friend class basic_reg_key<C, T, A>;
00330 #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
00331 
00333     basic_reg_value(hkey_type hkeyParent, string_type const& value_name)
00334         : m_name(value_name)
00335         , m_hkey(dup_key_(hkeyParent, KEY_READ))
00336         , m_type(REG_NONE)
00337         , m_bTypeRetrieved(ws_false_v)
00338     {} // Implementation provided here, as otherwise VC5 will not link
00339 public:
00341     ~basic_reg_value() stlsoft_throw_0();
00342 
00344     class_type& operator =(class_type const& rhs);
00346 
00349 public:
00366     ws_dword_t  type() const;
00367 
00369     string_type name() const;
00370 
00374     string_type value_sz() const;
00378     string_type value_expand_sz() const;
00380     ws_dword_t  value_dword() const;
00382     ws_dword_t  value_dword_littleendian() const;
00384     ws_dword_t  value_dword_bigendian() const;
00386     blob_type   value_binary() const;
00387 #ifndef WINSTL_REG_VALUE_NO_MULTI_SZ
00389     strings_type value_multi_sz() const;
00390 #endif /* !WINSTL_REG_VALUE_NO_MULTI_SZ */
00392 
00395 private:
00396     ws_dword_t          get_type_() const;
00397     static hkey_type    dup_key_(hkey_type hkey, REGSAM accessMask/* , result_type *res */);
00399 
00402 private:
00403     string_type             m_name;             // The name of the value
00404     hkey_type               m_hkey;             // The parent key of the value
00405     ss_mutable_k ws_dword_t m_type;             // The type of the value
00406     ss_mutable_k ws_bool_t  m_bTypeRetrieved;   // Facilitates lazy evaluation of the type
00408 };
00409 
00410 /* Typedefs to commonly encountered types. */
00415 typedef basic_reg_value<ws_char_a_t, reg_traits<ws_char_a_t>, processheap_allocator<ws_char_a_t> >  reg_value_a;
00420 typedef basic_reg_value<ws_char_w_t, reg_traits<ws_char_w_t>, processheap_allocator<ws_char_w_t> >  reg_value_w;
00425 typedef basic_reg_value<TCHAR, reg_traits<TCHAR>, processheap_allocator<TCHAR> >                    reg_value;
00426 
00428 // Unit-testing
00429 
00430 #ifdef STLSOFT_UNITTEST
00431 # include "./unittest/reg_value_unittest_.h"
00432 #endif /* STLSOFT_UNITTEST */
00433 
00434 /* /////////////////////////////////////////////////////////////////////////
00435  * Implementation
00436  */
00437 
00438 #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
00439 
00440 template <ss_typename_param_k C, ss_typename_param_k T, ss_typename_param_k A>
00441 inline basic_reg_value<C, T, A>::basic_reg_value()
00442     : m_name()
00443     , m_hkey(NULL)
00444     , m_type(REG_NONE)
00445     , m_bTypeRetrieved(ws_false_v)
00446 {}
00447 
00448 template <ss_typename_param_k C, ss_typename_param_k T, ss_typename_param_k A>
00449 inline basic_reg_value<C, T, A>::basic_reg_value(class_type const& rhs)
00450     : m_name(rhs.m_name)
00451     , m_hkey(dup_key_(rhs.m_hkey, KEY_READ))
00452     , m_type(rhs.m_type)
00453     , m_bTypeRetrieved(rhs.m_bTypeRetrieved)
00454 {}
00455 
00456 #if 0
00457 template <ss_typename_param_k C, ss_typename_param_k T, ss_typename_param_k A>
00458 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)
00459     : m_name(value_name)
00460     , m_hkey(dup_key_(hkeyParent))
00461     , m_type(REG_NONE)
00462     , m_bTypeRetrieved(ws_false_v)
00463 {}
00464 #endif /* 0 */
00465 
00466 template <ss_typename_param_k C, ss_typename_param_k T, ss_typename_param_k A>
00467 inline basic_reg_value<C, T, A>::~basic_reg_value() stlsoft_throw_0()
00468 {
00469     if(m_hkey != NULL)
00470     {
00471         ::RegCloseKey(m_hkey);
00472     }
00473 }
00474 
00475 template <ss_typename_param_k C, ss_typename_param_k T, ss_typename_param_k A>
00476 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)
00477 {
00478     m_name              =   rhs.m_name;
00479     m_type              =   rhs.m_type;
00480     m_bTypeRetrieved    =   rhs.m_bTypeRetrieved;
00481 
00482     hkey_type   hkey    =   m_hkey;
00483     m_hkey              =   dup_key_(rhs.m_hkey, KEY_READ);
00484     if(hkey != NULL)
00485     {
00486         ::RegCloseKey(hkey);
00487     }
00488 
00489     return *this;
00490 }
00491 
00492 // Implementation
00493 template <ss_typename_param_k C, ss_typename_param_k T, ss_typename_param_k A>
00494 inline ws_dword_t basic_reg_value<C, T, A>::get_type_() const
00495 {
00496     if(!m_bTypeRetrieved)
00497     {
00498         size_type   data_size = 0;
00499 
00500 #ifndef STLSOFT_CF_MUTABLE_KEYWORD_SUPPORT
00501         /* A little-known trick, but a useful one for dealing with translators
00502          * lacking mutable support whilst disturbing code to the minimum degree.
00503          */
00504         ws_dword_t  &m_type             =   const_cast<ws_dword_t &>(this->m_type);
00505         ws_bool_t   &m_bTypeRetrieved   =   const_cast<ws_bool_t &>(this->m_bTypeRetrieved);
00506 #endif /* STLSOFT_CF_MUTABLE_KEYWORD_SUPPORT */
00507 
00508         if(0 == traits_type::reg_query_value(m_hkey, m_name.c_str(), m_type, NULL, data_size))
00509         {
00510             m_bTypeRetrieved = ws_true_v;
00511         }
00512     }
00513 
00514     return m_type;
00515 }
00516 
00517 template <ss_typename_param_k C, ss_typename_param_k T, ss_typename_param_k A>
00518 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 */)
00519 {
00520     if(NULL == hkey)
00521     {
00522         return NULL;
00523     }
00524     else
00525     {
00526         result_type res;
00527         HKEY        hkeyDup = traits_type::key_dup(hkey, accessMask, &res);
00528 
00529         if(ERROR_SUCCESS != res)
00530         {
00531 #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
00532             static const char message[] = "could not duplicate key";
00533 
00534             if(ERROR_ACCESS_DENIED == res)
00535             {
00536                 STLSOFT_THROW_X(access_denied_exception(message, res));
00537             }
00538             else
00539             {
00540                 STLSOFT_THROW_X(key_not_duplicated_exception(message, res));
00541             }
00542 #else /* ? STLSOFT_CF_EXCEPTION_SUPPORT */
00543             ::SetLastError(res);
00544             hkeyDup = NULL;
00545 #endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
00546         }
00547 
00548         return hkeyDup;
00549     }
00550 }
00551 
00552 
00553 // Attributes
00554 template <ss_typename_param_k C, ss_typename_param_k T, ss_typename_param_k A>
00555 inline ws_dword_t basic_reg_value<C, T, A>::type() const
00556 {
00557     return get_type_();
00558 }
00559 
00560 template <ss_typename_param_k C, ss_typename_param_k T, ss_typename_param_k A>
00561 inline ss_typename_type_ret_k basic_reg_value<C, T, A>::string_type basic_reg_value<C, T, A>::name() const
00562 {
00563     return m_name;
00564 }
00565 
00566 template <ss_typename_param_k C, ss_typename_param_k T, ss_typename_param_k A>
00567 inline ss_typename_type_ret_k basic_reg_value<C, T, A>::string_type basic_reg_value<C, T, A>::value_sz() const
00568 {
00569     // Does not expand environment strings
00570     string_type ret;
00571     size_type   data_size   =   0;
00572     ws_long_t   res         =   traits_type::reg_query_info(m_hkey, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &data_size, NULL, NULL);
00573 
00574     if(ERROR_SUCCESS != res)
00575     {
00576 #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
00577         static const char message[] = "could not determine the data size";
00578 
00579         if(ERROR_ACCESS_DENIED == res)
00580         {
00581             STLSOFT_THROW_X(access_denied_exception(message, res));
00582         }
00583         else
00584         {
00585             STLSOFT_THROW_X(registry_exception(message, res));
00586         }
00587 #endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
00588     }
00589     else if(data_size > 0) // Are there _any_ values have non-zero size
00590     {
00591         char_buffer_type_   buffer(1 + data_size);
00592         ws_dword_t          dw;
00593 
00594         data_size = buffer.size();
00595         res = traits_type::reg_query_value(m_hkey, m_name.c_str(), dw, &buffer[0], data_size);
00596 
00597         if(ERROR_SUCCESS != res)
00598         {
00599 #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
00600             static const char message[] = "could not elicit string value";
00601 
00602             if(ERROR_ACCESS_DENIED == res)
00603             {
00604                 STLSOFT_THROW_X(access_denied_exception(message, res));
00605             }
00606             else
00607             {
00608                 STLSOFT_THROW_X(registry_exception(message, res));
00609             }
00610 #endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
00611         }
00612         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
00613         {
00614             WINSTL_ASSERT(0 != data_size);
00615 
00616             --data_size; // This is required since the size contains space for the nul-terminator
00617 
00618             buffer[data_size / sizeof(char_type)] = 0; // The site of a former bug. Thanks to Diego Chanoux for spotting this
00619 
00620             ret.assign(buffer.data(), data_size / sizeof(char_type));
00621         }
00622     }
00623 
00624     return ret;
00625 }
00626 
00627 template <ss_typename_param_k C, ss_typename_param_k T, ss_typename_param_k A>
00628 inline ss_typename_type_ret_k basic_reg_value<C, T, A>::string_type basic_reg_value<C, T, A>::value_expand_sz() const
00629 {
00630     // Does expand environment strings
00631     string_type ret = value_sz();
00632 
00633     if( ret.length() > 0 &&
00634         REG_EXPAND_SZ == get_type_())
00635     {
00636         size_type size = traits_type::expand_environment_strings(ret.c_str(), NULL, 0);
00637 
00638         if(0 != size)
00639         {
00640             char_buffer_type_ buffer(1 + size);
00641 
00642             if(0 == traits_type::expand_environment_strings(ret.c_str(), &buffer[0], size))
00643             {
00644 #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
00645                 static const char   message[]   =   "could not expand environment strings";
00646                 DWORD               res         =   ::GetLastError();
00647 
00648                 if(ERROR_ACCESS_DENIED == res)
00649                 {
00650                     STLSOFT_THROW_X(access_denied_exception(message, res));
00651                 }
00652                 else
00653                 {
00654                     STLSOFT_THROW_X(registry_exception(message, res));
00655                 }
00656 #endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
00657             }
00658             else
00659             {
00660                 ret.assign(buffer.data(), size);
00661             }
00662         }
00663     }
00664 
00665     return ret;
00666 }
00667 
00668 template <ss_typename_param_k C, ss_typename_param_k T, ss_typename_param_k A>
00669 inline ws_dword_t basic_reg_value<C, T, A>::value_dword() const
00670 {
00671     ws_dword_t  dwValue;
00672     size_type   cbData  =   sizeof(dwValue);
00673     ws_dword_t  value_type;
00674     ws_long_t   res     =   traits_type::reg_query_value(m_hkey, m_name.c_str(), value_type, &dwValue, cbData);
00675 
00676     if(ERROR_SUCCESS != res)
00677     {
00678 #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
00679         static const char message[] = "could not query value";
00680 
00681         if(ERROR_ACCESS_DENIED == res)
00682         {
00683             STLSOFT_THROW_X(access_denied_exception(message, res));
00684         }
00685         else
00686         {
00687             STLSOFT_THROW_X(registry_exception(message, res));
00688         }
00689 #else /* ? STLSOFT_CF_EXCEPTION_SUPPORT */
00690         dwValue = 0;
00691 #endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
00692     }
00693 
00694     return dwValue;
00695 }
00696 
00697 #if 0
00698 template <ss_typename_param_k C, ss_typename_param_k T, ss_typename_param_k A>
00699 inline ws_dword_t basic_reg_value<C, T, A>::value_dword_littleendian() const
00700 {}
00701 
00702 template <ss_typename_param_k C, ss_typename_param_k T, ss_typename_param_k A>
00703 inline ws_dword_t basic_reg_value<C, T, A>::value_dword_bigendian() const
00704 {}
00705 #endif /* 0 */
00706 
00707 template <ss_typename_param_k C, ss_typename_param_k T, ss_typename_param_k A>
00708 inline ss_typename_type_ret_k basic_reg_value<C, T, A>::blob_type basic_reg_value<C, T, A>::value_binary() const
00709 {
00710     size_type   data_size   =   0;
00711     ws_dword_t  dw;
00712     ws_long_t   res         =   traits_type::reg_query_value(m_hkey, m_name.c_str(), dw, NULL, data_size);
00713 
00714     if(ERROR_SUCCESS != res)
00715     {
00716 #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
00717 
00718 query_failed:
00719 
00720         static const char message[] = "could not elicit binary value";
00721 
00722         if(ERROR_ACCESS_DENIED == res)
00723         {
00724             STLSOFT_THROW_X(access_denied_exception(message, res));
00725         }
00726         else
00727         {
00728             STLSOFT_THROW_X(registry_exception(message, res));
00729         }
00730 #endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
00731     }
00732     else
00733     {
00734         WINSTL_MESSAGE_ASSERT("queried registry value is not binary", dw == REG_BINARY);
00735 
00736         if(data_size > 0)
00737         {
00738             byte_buffer_type_   buffer(data_size);
00739 
00740             data_size = buffer.size();
00741             res = traits_type::reg_query_value(m_hkey, m_name.c_str(), dw, buffer.data(), data_size);
00742 
00743             if(ERROR_SUCCESS != res)
00744             {
00745 #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
00746                 goto query_failed;
00747 #endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
00748             }
00749             else
00750             {
00751                 return blob_type(buffer.data(), buffer.size());
00752             }
00753         }
00754     }
00755 
00756     return blob_type();
00757 }
00758 
00759 #ifndef WINSTL_REG_VALUE_NO_MULTI_SZ
00760 template <ss_typename_param_k C, ss_typename_param_k T, ss_typename_param_k A>
00761 inline ss_typename_type_ret_k basic_reg_value<C, T, A>::strings_type basic_reg_value<C, T, A>::value_multi_sz() const
00762 {
00763     strings_type    ret;
00764     size_type       data_size   =   0;
00765     ws_long_t       res         =   traits_type::reg_query_info(m_hkey, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &data_size, NULL, NULL);
00766 
00767     if(ERROR_SUCCESS != res)
00768     {
00769 #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
00770         static const char message[] = "could not determine the data size";
00771 
00772         if(ERROR_ACCESS_DENIED == res)
00773         {
00774             STLSOFT_THROW_X(access_denied_exception(message, res));
00775         }
00776         else
00777         {
00778             STLSOFT_THROW_X(registry_exception(message, res));
00779         }
00780 #endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
00781     }
00782     else if(data_size > 0) // Are there _any_ values have non-zero size
00783     {
00784         char_buffer_type_   buffer(1 + data_size);
00785         ws_dword_t          dw;
00786 
00787         data_size   =   buffer.size();
00788         res         =   traits_type::reg_query_value(m_hkey, m_name.c_str(), dw, &buffer[0], data_size);
00789 
00790         if(ERROR_SUCCESS != res)
00791         {
00792 #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
00793             static const char message[] = "could not elicit string values";
00794 
00795             if(ERROR_ACCESS_DENIED == res)
00796             {
00797                 STLSOFT_THROW_X(access_denied_exception(message, res));
00798             }
00799             else
00800             {
00801                 STLSOFT_THROW_X(registry_exception(message, res));
00802             }
00803 #endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
00804         }
00805         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
00806         {
00807             buffer[data_size / sizeof(char_type)] = 0;
00808 
00809             ss_typename_type_k char_buffer_type_::const_iterator start = buffer.begin();
00810 
00811             { for(ss_typename_type_k char_buffer_type_::const_iterator ii = buffer.begin(); buffer.end() != ii;)
00812             {
00813                 if (*ii != (char_type)0)
00814                 {
00815                     ++ii;
00816                     continue;
00817                 }
00818 
00819                 if ((*ii == (char_type)0) && (*start == (char_type)0))
00820                 {
00821                     break;
00822                 }
00823 
00824                 ret.push_back(start);
00825                 start = ++ii;
00826             }}
00827 
00828             if (*start != (char_type)0)
00829             {
00830                 ret.push_back(start);
00831             }
00832         }
00833     }
00834 
00835     return ret;
00836 }
00837 #endif /* !WINSTL_REG_VALUE_NO_MULTI_SZ */
00838 
00839 // reg_blob
00840 
00841 template<ss_typename_param_k A>
00842 inline reg_blob<A>::reg_blob()
00843     : m_buffer(0)
00844 {}
00845 
00846 template<ss_typename_param_k A>
00847 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)
00848     : m_buffer(n)
00849 {
00850     winstl_ns_qual_std(copy)(data, data + m_buffer.size(), m_buffer.begin());
00851 }
00852 
00853 template<ss_typename_param_k A>
00854 inline reg_blob<A>::reg_blob(ss_typename_type_k reg_blob<A>::class_type const& rhs)
00855     : m_buffer(rhs.size())
00856 {
00857     winstl_ns_qual_std(copy)(rhs.data(), rhs.data() + m_buffer.size(), m_buffer.begin());
00858 }
00859 
00860 template<ss_typename_param_k A>
00861 inline reg_blob<A>::~reg_blob() stlsoft_throw_0()
00862 {}
00863 
00864 template<ss_typename_param_k A>
00865 inline ss_typename_type_ret_k reg_blob<A>::size_type reg_blob<A>::size() const
00866 {
00867     return m_buffer.size();
00868 }
00869 
00870 template<ss_typename_param_k A>
00871 inline ss_typename_type_ret_k reg_blob<A>::const_pointer reg_blob<A>::data() const
00872 {
00873     return m_buffer.data();
00874 }
00875 
00876 template<ss_typename_param_k A>
00877 inline ss_typename_type_ret_k reg_blob<A>::const_iterator reg_blob<A>::begin() const
00878 {
00879     return m_buffer.begin();
00880 }
00881 
00882 template<ss_typename_param_k A>
00883 inline ss_typename_type_ret_k reg_blob<A>::const_iterator reg_blob<A>::end() const
00884 {
00885     return m_buffer.end();
00886 }
00887 
00888 #if defined(STLSOFT_LF_BIDIRECTIONAL_ITERATOR_SUPPORT)
00889 template<ss_typename_param_k A>
00890 inline ss_typename_type_ret_k reg_blob<A>::const_reverse_iterator reg_blob<A>::rbegin() const
00891 {
00892     return const_reverse_iterator(end());
00893 }
00894 
00895 template<ss_typename_param_k A>
00896 inline ss_typename_type_ret_k reg_blob<A>::const_reverse_iterator reg_blob<A>::rend() const
00897 {
00898     return const_reverse_iterator(begin());
00899 }
00900 #endif /* STLSOFT_LF_BIDIRECTIONAL_ITERATOR_SUPPORT */
00901 
00902 
00903 #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
00904 
00905 /* ////////////////////////////////////////////////////////////////////// */
00906 
00907 #ifndef _WINSTL_NO_NAMESPACE
00908 # if defined(_STLSOFT_NO_NAMESPACE) || \
00909      defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
00910 } // namespace winstl
00911 # else
00912 } // namespace winstl_project
00913 } // namespace stlsoft
00914 # endif /* _STLSOFT_NO_NAMESPACE */
00915 #endif /* !_WINSTL_NO_NAMESPACE */
00916 
00917 /* ////////////////////////////////////////////////////////////////////// */
00918 
00919 #endif /* WINSTL_INCL_WINSTL_REGISTRY_HPP_REG_VALUE */
00920 
00921 /* ///////////////////////////// end of file //////////////////////////// */

Generated on Fri Mar 5 06:32:53 2010 for STLSoft by  doxygen 1.5.4