Main Page   Modules   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

Registry.h

Go to the documentation of this file.
00001 // Copyright NVIDIA Corporation 2002-2004
00002 // TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, THIS SOFTWARE IS PROVIDED
00003 // *AS IS* AND NVIDIA AND ITS SUPPLIERS DISCLAIM ALL WARRANTIES, EITHER EXPRESS
00004 // OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY
00005 // AND FITNESS FOR A PARTICULAR PURPOSE.  IN NO EVENT SHALL NVIDIA OR ITS SUPPLIERS
00006 // BE LIABLE FOR ANY SPECIAL, INCIDENTAL, INDIRECT, OR CONSEQUENTIAL DAMAGES
00007 // WHATSOEVER (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS,
00008 // BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR ANY OTHER PECUNIARY LOSS)
00009 // ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF NVIDIA HAS
00010 // BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES 
00011 
00012 #pragma once
00013 
00015 #include "nvsg/nvsgapi.h"  // storage-class defines
00016 
00017 #if defined(_WIN32)
00018 # include "nvsgwindefs.h"
00019 # ifndef NOMINMAX
00020 #  define NOMINMAX // avoid problems with Microsoft definitions in windef.h and min/max from stl
00021 #  include <windows.h>
00022 #  include <winbase.h>
00023 #  undef NOMINMAX
00024 # else
00025 #  include <windows.h>
00026 #  include <winbase.h>
00027 # endif
00028 #endif
00029 
00030 #include "nvutil/Assert.h"
00031 #include <string>
00032 
00033 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
00034 namespace nvutil {
00035 
00036 typedef std::basic_string <TCHAR> tstring;
00037 
00038 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
00040 template <typename T> class RegVal
00041 {
00042 public:
00043   enum
00044   {
00045     DIRTY  = 1
00046   };
00047 
00049   RegVal( const TCHAR * value_name , const TCHAR * subkey, DWORD type, HKEY root=HKEY_LOCAL_MACHINE
00050         , const T& def=T() ); // T() provides initialization for fundamental types
00052   ~RegVal() {}
00054   RegVal<T>& operator=(const T& rhs);
00056   operator const T&(); 
00057 
00058 private:
00059   // not allowed
00060   RegVal(const RegVal<T>&) {}   // copying
00061   RegVal<T>& operator=(const RegVal<T>&) {} // assignment
00062   // for private use only
00063   DWORD create();
00064   DWORD read(T& out, DWORD nbytes);
00065   DWORD write(const T& in, DWORD nbytes);
00066 
00067 private:
00068   tstring  m_name;
00069   tstring  m_subkey;
00070   DWORD   m_type;
00071   HKEY    m_root;
00072   HKEY    m_hkey;
00073   DWORD   m_flags;
00074   T       m_default;
00075   T       m_data;
00076 };
00077 
00078 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
00079 template <class T>
00080 inline RegVal<T>::RegVal( const TCHAR * value_name
00081                         , const TCHAR * subkey
00082                         , DWORD type 
00083                         , HKEY root=HKEY_LOCAL_MACHINE
00084                         , const T& def=T() )
00085 : m_name(value_name)
00086 , m_subkey(subkey)
00087 , m_type(type)
00088 , m_root(root) 
00089 , m_flags(DIRTY)
00090 , m_default(def) 
00091 {
00092   if ( ERROR_SUCCESS==create() )
00093   {
00094     if ( ERROR_FILE_NOT_FOUND==read(m_data, sizeof(T)) )
00095     {
00096       if ( ERROR_SUCCESS==write(m_default, sizeof(T)) ) 
00097       {
00098         m_data = m_default; // update internal cache
00099         m_flags &= ~DIRTY; // no need to walk the registry with the very next read
00100       }
00101     }
00102   }
00103 }
00104 
00105 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
00106 template <class T>
00107 inline RegVal<T>& RegVal<T>::operator=(const T& rhs) 
00108 { 
00109   write(rhs, sizeof(T)); // write the registry
00110   m_data = rhs; // update internal data cache according 
00111   m_flags &= ~DIRTY; // no need to walk the registry with the very next read
00112   return *this; 
00113 }
00114 
00115 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
00116 template <class T>
00117 inline RegVal<T>::operator const T&() 
00118 {
00119   if ( m_flags & DIRTY ) {
00120     // need to read the registry for valid data
00121     if ( !(ERROR_SUCCESS==read(m_data, sizeof(T))) )
00122     {
00123       // reading failed, set to default
00124       m_data = m_default;
00125     }
00126     m_flags &= ~DIRTY; // assign data cache valid, no need to walk the 
00127                         // registry with the very next read
00128   }
00129   return m_data;
00130 }
00131 
00132 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
00133 template <class T>
00134 inline DWORD RegVal<T>::create()
00135 {
00136   DWORD err;
00137   DWORD dwDisposition;
00138 
00139   // create the key if not already exists
00140   if ( ERROR_SUCCESS == (err = RegCreateKeyEx( m_root
00141                                              , m_subkey.c_str()
00142                                              , 0
00143                                              , NULL
00144                                              , REG_OPTION_NON_VOLATILE
00145                                              , KEY_ALL_ACCESS
00146                                              , NULL
00147                                              , &m_hkey
00148                                              , &dwDisposition ))
00149      )
00150   {
00151     // close key
00152     RegCloseKey(m_hkey);
00153   }
00154 
00155   return err;
00156 }
00157 
00158 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
00159 template <class T>
00160 inline DWORD RegVal<T>::read(T& out, DWORD nbytes)
00161 {
00162   DWORD err;
00163   DWORD type;
00164   
00165   if ( ERROR_SUCCESS == (err = RegOpenKeyEx(m_root, m_subkey.c_str(), NULL, KEY_READ, &m_hkey)) ) {
00166     err = RegQueryValueEx(m_hkey, m_name.c_str(), NULL, &type, (LPBYTE)&out, &nbytes);
00167     __ASSERT((err==ERROR_SUCCESS)==(m_type==type)); // type mismatch!
00168     RegCloseKey(m_hkey);
00169   }
00170   return err;
00171 }
00172 
00173 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
00174 template<class T>
00175 inline DWORD RegVal<T>::write(const T& in, DWORD nbytes)
00176 {
00177   DWORD err;
00178 
00179   if ( ERROR_SUCCESS == (err = RegOpenKeyEx(m_root, m_subkey.c_str(), NULL, KEY_ALL_ACCESS, &m_hkey)) ) {
00180     err = RegSetValueEx(m_hkey, m_name.c_str(), NULL, m_type, (const LPBYTE)&in, nbytes);
00181     RegCloseKey(m_hkey);
00182   }
00183   return err;
00184 }
00185 
00186 //  DOXYGEN can't handle template specializations (warns about no matching class member found)
00187 #if ! defined( DOXYGEN_IGNORE )
00188 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
00189 // string type needs some specialization with read and write
00190 template<>
00191 inline DWORD RegVal<tstring>::read(tstring& out, DWORD nbytes)
00192 {
00193   DWORD err;
00194   DWORD type;
00195 
00196   if ( ERROR_SUCCESS == (err = RegOpenKeyEx(m_root, m_subkey.c_str(), NULL, KEY_READ, &m_hkey)) ) {
00197     // (1) call RegQueryValueEx with output data set to NULL to get the exact byte count required  
00198     if ( ERROR_SUCCESS == (err = RegQueryValueEx(m_hkey, m_name.c_str(), NULL, &type, NULL, &nbytes)) ) {
00199       // create a temporary tstring and resize its controlled sequence according
00200       // to the byte count received with the previous call to RegQueryValueEx()
00201       tstring tmp;
00202       tmp.resize(nbytes);
00203       // (2) call RegQueryValueEx with valid output buffer now to receive the requested data  
00204       if ( ERROR_SUCCESS == (err = RegQueryValueEx(m_hkey, m_name.c_str(), NULL, &type, (LPBYTE)tmp.data(), &nbytes)) ) {
00205         __ASSERT((err==ERROR_SUCCESS)==(m_type==type)); // type mismatch!
00206         // assign the c-string of the temporary string object rather than the string object itself to
00207         // ensure that the length of the output string's controlled sequence matches exactly that
00208         // of the enclosed c-string
00209         out = tmp.c_str();
00210       }
00211     }
00212     RegCloseKey(m_hkey);
00213   }
00214   return err;
00215 }
00216 
00217 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
00218 template<>
00219 inline DWORD RegVal<tstring>::write(const tstring& in, DWORD nbytes)
00220 {
00221   DWORD err;
00222 
00223   if ( ERROR_SUCCESS == (err = RegOpenKeyEx(m_root, m_subkey.c_str(), NULL, KEY_ALL_ACCESS, &m_hkey)) ) {
00224     err = RegSetValueEx(m_hkey, m_name.c_str(), NULL, m_type, (const LPBYTE)in.c_str(), nbytes);
00225     RegCloseKey(m_hkey);
00226   }
00227   return err;
00228 }
00229 
00230 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
00231 template<>
00232 inline RegVal<tstring>& RegVal<tstring>::operator=(const tstring& rhs) 
00233 { 
00234   // determine required byte count
00235   DWORD nbytes = (DWORD)rhs.length()+1; // including terminating 0
00236   nbytes *= sizeof(TCHAR);
00237 
00238   // write to registry now
00239   write(rhs, nbytes);
00240 
00241   m_data = rhs; // update internal data cache according 
00242   m_flags &= ~DIRTY; // no need to walk the registry with the very next read
00243 
00244   return *this; 
00245 }
00246 #endif  //  DOXYGEN_IGNORE
00247     
00248 } // namespace nvutil
00249 
00250 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
00251 // avoid tedious, repeated qualification of namespace scope
00252 //using nvutil::RegVal;
00253 

Generated on Tue Mar 1 13:19:18 2005 for NVSGSDK by NVIDIA