Main Page | Modules | Namespace List | Class Hierarchy | Class List | File List | Namespace Members | Class Members | File Members | Related Pages
registry.h
Go to the documentation of this file.00001 00004 /* 00005 * Copyright © 2000, 2001 Paul Hollingsworth 00006 * 00007 * This material is provided "as is", with absolutely no warranty 00008 * expressed or implied. Any use is at your own risk. Permission to 00009 * use or copy this software for any purpose is hereby granted without 00010 * fee, provided the above notices are retained on all copies. 00011 * Permission to modify the code and to distribute modified code is 00012 * granted, provided the above notices are retained, and a notice that 00013 * the code was modified is included with the above copyright notice. 00014 * 00015 * This header is part of comet. 00016 * http://www.lambdasoft.dk/comet 00017 */ 00018 00019 #ifndef COMET_REGISTRY_H 00020 #define COMET_REGISTRY_H 00021 00022 #include <windows.h> 00023 00024 #include <comet/reference_count.h> 00025 #include <comet/assert.h> 00026 #include <comet/tstring.h> 00027 00028 #ifdef __BORLANDC__ 00029 #define COMET_ITERATOR_VOID(tag) std::iterator<tag, void, void, void *, void > 00030 #else 00031 #ifndef __SGI_STL 00032 #ifdef __MINGW32__ 00033 #define COMET_ITERATOR_VOID(tag) std::forward_iterator<tag, void> 00034 #else 00035 #ifdef _CPPLIB_VER 00036 #define COMET_ITERATOR_VOID(tag) std::iterator<tag, void, void, void, void> 00037 #else 00038 #define COMET_ITERATOR_VOID(tag) std::iterator<tag, void, void> 00039 #endif 00040 #endif 00041 #else 00042 #define COMET_ITERATOR_VOID(tag) std::iterator<tag, void, void, void, void> 00043 #endif 00044 #endif 00045 00046 namespace comet { 00049 namespace registry { 00051 // typedef std::basic_string<TCHAR> tstring; 00052 00053 namespace impl { 00054 // Only when an iterator is dereferenced 00055 // do we want to go about reading the value 00056 // from the registry. This requires us to create 00057 // a temporary object. But in order to overload 00058 // operator->, our temporary object must overload 00059 // operator-> - and often it doesn't. 00060 // Proxy is here to effectively overload operator-> for the temporary 00061 // object. 00062 template<typename T> 00063 class proxy 00064 { 00065 T t_; 00066 public: 00067 proxy(const T &t) : t_(t) {} 00068 T *operator->() 00069 { 00070 return &t_; 00071 } 00072 00073 const T *operator->() const 00074 { 00075 return &t_; 00076 } 00077 }; 00078 00079 class key_base 00080 { 00081 HKEY key_; 00082 mutable reference_count rc_; 00083 00084 static bool valid_key_(HKEY key) { 00085 return key != 0; 00086 } 00087 00088 void close_() { 00089 if(valid_key_(key_) && (--rc_ == 0)) { 00090 LONG errcode = ::RegCloseKey(key_); 00091 COMET_ASSERT(ERROR_SUCCESS == errcode); 00092 /* C4189 */ errcode; 00093 } 00094 key_ = 0; // invalidate key handle 00095 } 00096 public: 00097 key_base(const key_base &rhs) 00098 : key_(rhs.key_) { 00099 if(valid_key_(key_)) 00100 ++rhs.rc_; 00101 rc_ = rhs.rc_; 00102 } 00103 00104 key_base(HKEY key = 0) : key_(key) { 00105 } 00106 00107 ~key_base() throw() { 00108 close_(); 00109 } 00110 00111 key_base &operator=(const key_base &rhs) 00112 { 00113 key_base tmp(rhs); 00114 swap(tmp); 00115 return *this; 00116 } 00117 00118 void swap(key_base &rhs) throw() { 00119 std::swap(key_, rhs.key_); 00120 std::swap(rc_, rhs.rc_); 00121 } 00122 00123 LONG open(const tstring &subkey, 00124 REGSAM sam_desired, 00125 HKEY *childkey) const { 00126 *childkey = 0; 00127 return ::RegOpenKeyEx(key_, 00128 subkey.c_str(), 00129 0, 00130 sam_desired, 00131 childkey); 00132 } 00133 00134 HKEY open_nothrow(const tstring &subkey, 00135 REGSAM sam_desired, 00136 LONG *errcode) const { 00137 HKEY childkey_ = 0; 00138 LONG errcode_ = open(subkey, 00139 sam_desired, 00140 &childkey_); 00141 if(errcode) *errcode = errcode_; 00142 return childkey_; 00143 } 00144 00145 LONG create(const tstring &subkey, 00146 DWORD options, 00147 REGSAM sam_desired, 00148 LPSECURITY_ATTRIBUTES security_attributes, 00149 LPDWORD disposition, 00150 HKEY *childkey) const { 00151 return ::RegCreateKeyEx(key_, 00152 subkey.c_str(), 00153 0, 00154 REG_NONE, 00155 options, 00156 sam_desired, 00157 security_attributes, 00158 childkey, 00159 disposition); 00160 } 00161 00162 HKEY create_nothrow(const tstring &subkey, 00163 DWORD options, 00164 REGSAM sam_desired, 00165 LPSECURITY_ATTRIBUTES security_attributes, 00166 LPDWORD disposition, 00167 LONG *errcode) const { 00168 HKEY childkey = 0; 00169 LONG errcode_ = create(subkey, 00170 options, 00171 sam_desired, 00172 security_attributes, 00173 disposition, 00174 &childkey); 00175 if(errcode) *errcode = errcode_; 00176 return childkey; 00177 } 00178 00179 LONG flush_nothrow() const { 00180 return ::RegFlushKey(key_); 00181 } 00182 00183 LONG delete_subkey_nothrow(const tstring &subkey) const { 00184 return ::RegDeleteKey(key_, subkey.c_str()); 00185 } 00186 00187 LONG delete_value_nothrow(const tstring &value_name) const { 00188 return ::RegDeleteValue(key_, value_name.c_str()); 00189 } 00190 00191 void close() { 00192 close_(); 00193 } 00194 00195 HKEY get() const { 00196 return key_; 00197 } 00198 00199 bool is_valid() const throw() 00200 { 00201 return key_ ? true : false; 00202 } 00203 00204 operator const void *() const throw() 00205 { 00206 return is_valid() ? this : 0; 00207 } 00208 }; // class key_base 00209 00210 // Enumerating through keys or values is 00211 // very similar. These two class encapsulate 00212 // all that is different between the two algorithms. 00213 struct next_value 00214 { 00215 static LONG perform(HKEY key, 00216 DWORD dwIndex, 00217 LPTSTR lpName, 00218 LPDWORD lpcName) 00219 { 00220 return ::RegEnumValue(key, dwIndex, lpName, lpcName, 0, 0, 0, 0); 00221 } 00222 }; 00223 00224 struct next_key 00225 { 00226 static LONG perform(HKEY key, 00227 DWORD dwIndex, 00228 LPTSTR lpName, 00229 LPDWORD lpcName) 00230 { 00231 return ::RegEnumKeyEx(key, dwIndex, lpName, lpcName, 0, 0, 0, 0); 00232 } 00233 }; 00234 } // namespace impl 00235 00236 00241 template<class error_policy, class get_next> 00242 struct name_iterator : public COMET_ITERATOR_VOID(std::forward_iterator_tag) 00243 { 00244 // key_ is the only assignment that can fail. So 00245 // we make it the first member, so that 00246 // default assignment is exception safe. 00247 impl::key_base key_; 00248 DWORD index_; 00249 DWORD buf_size_; 00250 DWORD num_values_; 00251 00252 static void check_exception_(LONG errcode) 00253 { 00254 if(ERROR_SUCCESS != errcode) 00255 error_policy::on_error(errcode); 00256 } 00257 00258 // Is this iterator an end iterator? 00259 bool is_end() const 00260 { 00261 return key_ ? false : true; 00262 } 00263 00264 // Make this iterator an end 00265 // iterator 00266 void make_end() 00267 { 00268 key_.close(); 00269 } 00270 00271 public: 00272 typedef tstring value_type; 00273 name_iterator(const impl::key_base &key, 00274 DWORD num_values, 00275 DWORD buf_size) 00276 : key_(key), 00277 num_values_(num_values), 00278 buf_size_(buf_size), 00279 index_(0) 00280 { 00281 if(0 == num_values) 00282 make_end(); 00283 } 00284 00285 void swap(name_iterator &rhs) 00286 { 00287 key_.swap(rhs.key_); 00288 std::swap(index_, rhs.index_); 00289 std::swap(buf_size_, rhs.buf_size_); 00290 std::swap(num_values_, rhs.num_values_); 00291 } 00292 00293 name_iterator &operator=(const name_iterator &rhs) 00294 { 00295 key_ = rhs.key_; 00296 index_ = rhs.index_; 00297 buf_size_ = rhs.buf_size_; 00298 num_values_ = rhs.num_values_; 00299 return *this; 00300 } 00301 00302 impl::key_base key() const 00303 { 00304 return key_; 00305 } 00306 00307 name_iterator() 00308 { 00309 make_end(); 00310 } 00311 00312 value_type operator*() const 00313 { 00314 tstring::value_type *buf = static_cast<tstring::value_type *>(_alloca(buf_size_)); 00315 DWORD dummy = buf_size_; 00316 check_exception_(get_next::perform(key_.get(), 00317 index_, 00318 buf, 00319 &dummy)); 00320 return buf; 00321 } 00322 00323 impl::proxy<value_type> operator->() const 00324 { 00325 return **this; 00326 } 00327 00328 name_iterator &operator++() 00329 { 00330 ++index_; 00331 if(index_ == num_values_) 00332 make_end(); 00333 return *this; 00334 } 00335 00336 name_iterator operator++(int) const 00337 { 00338 name_iterator retval = *this; 00339 ++(*this); 00340 return retval; 00341 } 00342 00343 bool operator==(const name_iterator &rhs) const 00344 { 00345 if(is_end()) return rhs.is_end(); 00346 if(rhs.is_end()) return is_end(); 00347 return index_ == rhs.index_; 00348 } 00349 00350 bool operator!=(const name_iterator &rhs) const 00351 { 00352 return !(*this == rhs); 00353 } 00354 }; 00355 00361 template<class error_policy> 00362 class value 00363 { 00364 impl::key_base key_; 00365 tstring value_name_; 00366 static void check_exception_(LONG errcode) 00367 { 00368 if(ERROR_SUCCESS != errcode) 00369 error_policy::on_error(errcode); 00370 } 00371 static void type_mismatch() 00372 { 00373 error_policy::on_typemismatch(); 00374 } 00375 00376 LONG get_value_(DWORD *type, 00377 BYTE *buffer, 00378 DWORD *number_bytes) const 00379 { 00380 return ::RegQueryValueEx(key_.get(), 00381 value_name_.c_str(), 00382 0, 00383 type, 00384 buffer, 00385 number_bytes); 00386 } 00387 00388 void get_value(DWORD *type, 00389 BYTE *buffer, 00390 DWORD *number_bytes) const { 00391 check_exception_( 00392 get_value_(type, 00393 buffer, 00394 number_bytes) 00395 ); 00396 } 00397 00398 LONG set_value_(DWORD type, 00399 const BYTE *data, 00400 DWORD number_bytes) 00401 { 00402 return ::RegSetValueEx(key_.get(), 00403 value_name_.c_str(), 00404 0, 00405 type, 00406 data, 00407 number_bytes); 00408 } 00409 00410 void set_value(DWORD type, 00411 const BYTE *data, 00412 DWORD number_bytes) 00413 { 00414 check_exception_( 00415 set_value_(type, 00416 data, 00417 number_bytes)); 00418 } 00419 00420 tstring name() const 00421 { 00422 return value_name_; 00423 } 00424 public: 00425 00427 00440 bool exists() const 00441 { 00442 return ERROR_SUCCESS == get_value_(0, 0, 0); 00443 } 00444 00445 value(const impl::key_base &key, 00446 const tstring &value_name) 00447 : key_(key), 00448 value_name_(value_name) 00449 { 00450 } 00451 00453 00458 void swap(value &rhs) 00459 { 00460 key_.swap(rhs.key_); 00461 value_name_.swap(rhs.value_name_); 00462 } 00463 00464 00466 00471 void get(DWORD *type, 00472 BYTE *buffer, 00473 DWORD *number_bytes) const 00474 { 00475 get_value(type, 00476 buffer, 00477 number_bytes); 00478 } 00479 00481 00486 LONG get_nothrow(DWORD *type, 00487 BYTE *buffer, 00488 DWORD *number_bytes) const 00489 { 00490 return get_value_(type, buffer, number_bytes); 00491 } 00492 00494 00499 void set(DWORD type, 00500 const BYTE *buffer, 00501 DWORD number_bytes) 00502 { 00503 set_value(type, 00504 buffer, 00505 number_bytes); 00506 } 00507 00509 00514 LONG set_nothrow(DWORD type, 00515 const BYTE *buffer, 00516 DWORD number_bytes) 00517 { 00518 return set_value_(type, buffer, bytes); 00519 } 00520 00522 00525 tstring str() const 00526 { 00527 DWORD number_bytes = 0; 00528 DWORD type; 00529 get_value(&type, 00530 0, 00531 &number_bytes); 00532 if( (REG_SZ != type) && (REG_EXPAND_SZ != type)) 00533 type_mismatch(); 00534 BYTE *buffer = static_cast<BYTE *>(_alloca(number_bytes)); 00535 get_value(0, 00536 buffer, 00537 &number_bytes); 00538 return tstring(reinterpret_cast<const tstring::value_type *>(buffer), 00539 (number_bytes/sizeof(tstring::value_type)) - 1); 00540 } 00541 00542 tstring str(const tstring& default_val) const 00543 { 00544 DWORD number_bytes = 0; 00545 DWORD type; 00546 if (get_value_(&type, 00547 0, 00548 &number_bytes) != ERROR_SUCCESS) return default_val; 00549 if( (REG_SZ != type) && (REG_EXPAND_SZ != type)) 00550 type_mismatch(); 00551 BYTE *buffer = static_cast<BYTE *>(_alloca(number_bytes)); 00552 get_value(0, 00553 buffer, 00554 &number_bytes); 00555 return tstring(reinterpret_cast<const tstring::value_type *>(buffer), 00556 (number_bytes/sizeof(tstring::value_type)) - 1); 00557 } 00558 00560 operator tstring() const 00561 { 00562 return str(); 00563 } 00564 00566 operator DWORD() const 00567 { 00568 return dword(); 00569 } 00570 00572 00575 DWORD dword() const 00576 { 00577 DWORD number_bytes = sizeof( DWORD ); 00578 DWORD type; 00579 DWORD retval; 00580 get_value(&type, 00581 reinterpret_cast<BYTE *>(&retval), 00582 &number_bytes); 00583 if( (REG_DWORD != type) && (REG_DWORD_LITTLE_ENDIAN != type) ) 00584 type_mismatch(); 00585 return retval; 00586 } 00587 00588 DWORD dword(DWORD default_val) const 00589 { 00590 DWORD number_bytes = sizeof( DWORD ); 00591 DWORD type; 00592 DWORD retval; 00593 if (get_value_(&type, 00594 reinterpret_cast<BYTE *>(&retval), 00595 &number_bytes) != ERROR_SUCCESS) return default_val; 00596 if( (REG_DWORD != type) && (REG_DWORD_LITTLE_ENDIAN != type) ) 00597 type_mismatch(); 00598 return retval; 00599 } 00600 00601 // These two operators are currently useless 00602 // because VC++ 6.0 appears to have a bug - 00603 // it claims that no conversion to pair<string,string> 00604 // exists even though it clearly does here. 00605 // However, it's possible these would be 00606 // useful on other compilers (or future compilers). 00607 operator std::pair<tstring, tstring>() const 00608 { 00609 return std::make_pair(name(), str()); 00610 } 00611 00612 operator std::pair<tstring, DWORD>() const 00613 { 00614 return std::make_pair(name(), dword()); 00615 } 00616 00618 value &operator=(const tstring &rhs) 00619 { 00620 set_value(REG_SZ, 00621 reinterpret_cast<const BYTE *>(rhs.c_str()), 00622 (rhs.length() + 1) * sizeof ( tstring::value_type)); 00623 return *this; 00624 } 00625 00627 value &operator=(const DWORD &rhs) 00628 { 00629 set_value(REG_DWORD, 00630 reinterpret_cast<const BYTE *>(&rhs), 00631 sizeof (DWORD) ); 00632 return *this; 00633 } 00634 00636 value &operator=(int rhs) 00637 { 00638 return *this = DWORD(rhs); 00639 } 00640 00642 00647 value &operator=(const value &rhs) 00648 { 00649 DWORD type; 00650 DWORD size; 00651 rhs.get_value(&type, 00652 0, 00653 &size); 00654 BYTE *buffer = static_cast<BYTE *>(_alloca(size)); 00655 rhs.get_value_(0, 00656 buffer, 00657 &size); 00658 set_value(type, 00659 buffer, 00660 size); 00661 return *this; 00662 } 00663 }; // class value 00664 00668 template<typename error_policy> 00669 class const_value_iterator : public COMET_ITERATOR_VOID(std::forward_iterator_tag) 00670 { 00671 typedef const value<error_policy> second_type; 00672 typedef std::pair<const tstring, second_type > value_type_; 00673 00674 value_type_ get_value() const 00675 { 00676 tstring name = *index_; 00677 return std::make_pair(name, second_type(index_.key(), name) ); 00678 } 00679 protected: 00680 name_iterator<error_policy, impl::next_value> index_; 00681 public: 00682 typedef value_type_ value_type; 00683 00684 const_value_iterator(const impl::key_base &key, 00685 DWORD num_values, 00686 DWORD buf_size) 00687 : index_(key, num_values, buf_size) 00688 { 00689 } 00690 00691 const_value_iterator() {} 00692 00693 void swap(const_value_iterator &rhs) 00694 { 00695 index_.swap(rhs.index_); 00696 } 00697 00698 value_type operator*() const 00699 { 00700 return get_value(); 00701 } 00702 00703 const_value_iterator &operator++() 00704 { 00705 ++index_; 00706 return *this; 00707 } 00708 00709 const_value_iterator operator++(int) 00710 { 00711 const_value_iterator retval(*this); 00712 ++(*this); 00713 return retval; 00714 } 00715 00716 impl::proxy<value_type> operator->() 00717 { 00718 return **this; 00719 } 00720 00721 bool operator==(const const_value_iterator &rhs) const 00722 { 00723 return index_ == rhs.index_; 00724 } 00725 00726 bool operator!=(const const_value_iterator &rhs) const 00727 { 00728 return index_ != rhs.index_; 00729 } 00730 }; 00731 00735 template<typename error_policy> 00736 class value_iterator : public const_value_iterator<error_policy> 00737 { 00738 typedef value<error_policy> second_type; 00739 typedef std::pair<const tstring, second_type> value_type_; 00740 typedef const_value_iterator<error_policy> base; 00741 value_type_ get_value() const 00742 { 00743 tstring name = *index_; 00744 return std::make_pair(name, second_type(index_.key(), name) ); 00745 } 00746 00747 public: 00748 typedef value_type_ value_type; 00749 value_iterator(const impl::key_base &key, 00750 DWORD num_values, 00751 DWORD buf_size) 00752 : base(key, num_values, buf_size) {} 00753 00754 value_iterator() {} 00755 00756 value_type operator*() const 00757 { 00758 return get_value(); 00759 } 00760 00761 value_iterator &operator++() 00762 { 00763 base::operator++(); 00764 return *this; 00765 } 00766 00767 value_iterator operator++(int) 00768 { 00769 value_iterator retval(*this); 00770 ++(*this); 00771 return retval; 00772 } 00773 00774 impl::proxy<value_type> operator->() 00775 { 00776 return get_value(); 00777 } 00778 00779 bool operator==(const value_iterator &rhs) const 00780 { 00781 return index_ == rhs.index_; 00782 } 00783 00784 bool operator!=(const value_iterator &rhs) const 00785 { 00786 return index_ != rhs.index_; 00787 } 00788 }; 00789 00794 template<typename error_policy, 00795 typename iterator_, 00796 typename const_iterator_ = iterator_> 00797 struct collection 00798 { 00799 impl::key_base key_; 00800 DWORD num_values_; 00801 DWORD buf_size_; 00802 00803 public: 00804 collection(const impl::key_base &key, 00805 DWORD num_values, 00806 DWORD buf_size) 00807 : key_(key), 00808 num_values_(num_values), 00809 buf_size_(buf_size) 00810 { 00811 } 00812 00813 typedef iterator_ iterator; 00814 typedef const_iterator_ const_iterator; 00815 typedef typename iterator_::value_type value_type; 00816 typedef size_t size_type; 00817 00819 size_type size() const { return num_values_; } 00820 00822 void swap(collection &rhs) 00823 { 00824 key_.swap(rhs.key_); 00825 std::swap(num_values_, rhs.num_values_); 00826 std::swap(buf_size_, rhs.buf_size_); 00827 } 00828 00830 iterator begin() 00831 { 00832 return iterator(key_, num_values_, buf_size_); 00833 } 00834 00836 iterator end() 00837 { 00838 return iterator(); 00839 } 00840 00841 const_iterator begin() const 00842 { 00843 return const_iterator(key_, num_values_, buf_size_); 00844 } 00845 00846 const_iterator end() const 00847 { 00848 return const_iterator(); 00849 } 00850 }; 00851 00855 template<typename error_policy> 00856 class info 00857 { 00858 // Make key_ the first member - this 00859 // ensures exception safe assignment. 00860 impl::key_base key_; 00861 00862 // Number of values 00863 DWORD num_values_; 00864 00865 // Maximum length of a value name 00866 DWORD value_name_tchars_; 00867 00868 // Number of sub keys 00869 DWORD num_subkeys_; 00870 00871 // Maximum length of a sub key name 00872 DWORD subkey_name_tchars_; 00873 00874 static void check_exception_(LONG errcode) 00875 { 00876 if(ERROR_SUCCESS != errcode) 00877 error_policy::on_error(errcode); 00878 } 00879 00880 static DWORD bytes(DWORD tchars) 00881 { 00882 return (tchars + 1) * sizeof( tstring::value_type); 00883 } 00884 public: 00885 info(const impl::key_base &key) 00886 : key_(key) 00887 { 00888 check_exception_(::RegQueryInfoKey(key_.get(), 00889 0, // lpClass - reserved 00890 0, // lpcClass - reserved 00891 0, // lpReserved 00892 &num_subkeys_, 00893 &subkey_name_tchars_, 00894 0, // lpcMaxClassLen - I think this is also reserved 00895 &num_values_, 00896 &value_name_tchars_, 00897 0, // lpcMaxValueLen - not necessary for us 00898 0, // lpcbSecurityDescriptor 00899 0)); // lpftLastWriteTime 00900 } 00901 00903 void swap(info &rhs) 00904 { 00905 key_.swap(rhs.key_); 00906 std::swap(num_subkeys_, rhs.num_subkeys_); 00907 std::swap(subkey_name_tchars_, rhs.subkey_name_tchars_); 00908 std::swap(value_name_tchars_, rhs.value_name_tchars_); 00909 std::swap(num_values_, rhs.num_values_); 00910 } 00911 00913 typedef collection<error_policy, value_iterator<error_policy>, const_value_iterator<error_policy> > values_type; 00914 00916 typedef collection<error_policy, name_iterator<error_policy, impl::next_value> > value_names_type; 00917 00919 typedef collection<error_policy, name_iterator<error_policy, impl::next_key> > subkeys_type; 00920 00922 size_t num_values() const 00923 { 00924 return num_values_; 00925 } 00926 00928 size_t num_subkeys() const 00929 { 00930 return num_subkeys_; 00931 } 00932 00934 size_t max_value_name() const 00935 { 00936 return value_name_tchars_; 00937 } 00938 00940 size_t max_subkey_name() const 00941 { 00942 return subkey_name_tchars_; 00943 } 00944 00946 00973 values_type values() const 00974 { 00975 return values_type(key_, num_values_, bytes(value_name_tchars_)); 00976 } 00977 00979 00987 value_names_type value_names() const 00988 { 00989 return value_names_type(key_, num_values_, bytes(value_name_tchars_)); 00990 } 00991 00993 01001 subkeys_type subkeys() const 01002 { 01003 return subkeys_type(key_, num_subkeys_, bytes(subkey_name_tchars_)); 01004 } 01005 }; 01006 01007 #ifdef __BORLANDC__ 01008 using impl::key_base; 01009 #endif 01010 01037 template<class error_policy> 01038 class key : private impl::key_base { 01039 private: 01040 static void check_exception_(LONG errcode) 01041 { 01042 if(ERROR_SUCCESS != errcode) 01043 error_policy::on_error(errcode); 01044 } 01045 public: 01046 key(HKEY key_handle = 0) : key_base(key_handle) {} 01047 01049 01056 key(const key &rhs) 01057 : key_base(rhs) { 01058 } 01060 01062 key( const impl::key_base &rhs) 01063 : key_base(rhs) { 01064 } 01065 01066 void swap(key &rhs) 01067 { 01068 key_base::swap(rhs); 01069 } 01070 01072 01086 operator const void *() const throw() 01087 { 01088 return is_valid() ? this : 0; 01089 } 01090 01091 01093 key open(const tstring &subkey, 01094 REGSAM sam_desired = KEY_ALL_ACCESS) const { 01095 HKEY childkey_ = 0; 01096 check_exception_( 01097 key_base::open(subkey, 01098 sam_desired, 01099 &childkey_) 01100 ); 01101 return childkey_; 01102 } 01103 01105 key open_nothrow(const tstring &subkey, 01106 REGSAM sam_desired = KEY_ALL_ACCESS, 01107 LONG *errcode = 0) const { 01108 return key_base::open_nothrow(subkey, 01109 sam_desired, errcode); 01110 } 01111 01113 key create(const tstring &subkey, 01114 DWORD options = REG_OPTION_NON_VOLATILE, 01115 REGSAM sam_desired = KEY_ALL_ACCESS, 01116 LPSECURITY_ATTRIBUTES security_attributes = 0, 01117 LPDWORD disposition = 0) const { 01118 HKEY childkey_ = 0; 01119 check_exception_( 01120 key_base::create(subkey, 01121 options, 01122 sam_desired, 01123 security_attributes, 01124 disposition, 01125 &childkey_) 01126 ); 01127 return childkey_; 01128 } 01129 01131 key create_nothrow(const tstring &subkey, 01132 DWORD options = REG_OPTION_NON_VOLATILE, 01133 REGSAM sam_desired = KEY_ALL_ACCESS, 01134 LPSECURITY_ATTRIBUTES security_attributes = 0, 01135 LPDWORD disposition = 0, 01136 LONG *errcode = 0) const { 01137 return key_base::create_nothrow(subkey, 01138 options, 01139 sam_desired, 01140 security_attributes, 01141 disposition, 01142 errcode); 01143 } 01144 01146 void flush() const { 01147 check_exception_( 01148 flush_nothrow() 01149 ); 01150 } 01151 01153 LONG flush_nothrow() const { 01154 return key_base::flush_nothrow(); 01155 } 01156 01158 01164 void delete_subkey(const tstring &subkey) const { 01165 check_exception_( 01166 delete_subkey_nothrow(subkey.c_str()) 01167 ); 01168 } 01169 01171 01177 LONG delete_subkey_nothrow(const tstring &subkey) const { 01178 return key_base::delete_subkey_nothrow(subkey); 01179 } 01180 01182 void delete_value(const tstring &value_name) const { 01183 check_exception_( 01184 delete_value_nothrow(value_name) 01185 ); 01186 } 01187 01189 LONG delete_value_nothrow(const tstring &value_name) const { 01190 return key_base::delete_value_nothrow(value_name); 01191 } 01192 01194 01198 void close() { 01199 key_base::close(); 01200 } 01201 01203 HKEY get() const { 01204 return key_base::get(); 01205 } 01206 01207 typedef value<error_policy> mapped_type; 01208 01209 // All of these methods are const because I figured 01210 // it was more useful. It allows you to create 01211 // temporary regkey objects for the purposes of 01212 // updating. 01213 01215 01222 mapped_type get_value(const tstring &value_name = _T("")) const 01223 { 01224 return mapped_type(*this, value_name); 01225 } 01226 01228 01235 mapped_type operator[](const tstring &value_name) const 01236 { 01237 return get_value(value_name); 01238 } 01239 01241 typedef info<error_policy> info_type; 01243 typedef typename info_type::subkeys_type subkeys_type; 01245 typedef typename info_type::values_type values_type; 01247 typedef typename info_type::value_names_type value_names_type; 01248 01250 01265 info_type enumerate() const 01266 { 01267 return info_type(*this); 01268 } 01269 01271 key &operator*() 01272 { 01273 return *this; 01274 } 01275 01277 template<typename T> 01278 key &operator=(const T &val) 01279 { 01280 get_value(val.first) = val.second; 01281 return *this; 01282 } 01283 01287 //template<> 01288 key &operator=(const key &rhs) 01289 { 01290 key_base::operator=(rhs); 01291 return *this; 01292 } 01293 01295 key &operator++() { return *this; } 01297 key &operator++(int) { return *this; } 01298 }; // class key 01299 } // namespace registry 01300 } // namespace comet 01301 01302 #endif // COMET_REGISTRY_H