|
// Registry.hpp : various MS Windows Registry wrappers and helpers.
//
// (todo) add clean and proper ASCII/Unicode versions/overloads.
//
////////////////////////////////////////////////////////////////////////////////
#pragma once
#include "debugMacros.hpp"
#include <iterator>
#include <string>
#ifndef _UNICODE
#define OLE2ANSI
#endif
#include <tchar.h>
// (todo) move to a separate/appropriate module along with other string helpers.
typedef std::basic_string<TCHAR> tstring;
////////////////////////////////////////////////////////////////////////////////
//
// WinString
// ---------
//
// A small helper class used for saving the length of C strings along the
// strings themselves thus avoiding redundant strlen() calls. Useful for many
// Windows API functions that report/return this length.
//
// (todo) currently only a 'helper class', move to a separate/appropriate
// module.
//
// (todo) perhaps think of a better name for the class.
//
////////////////////////////////////////////////////////////////////////////////
class WinString
{
public:
WinString() {}
WinString( TCHAR const * const string, DWORD const length ) : string_( string ), length_( length ) {}
TCHAR const * c_str () const { return string_; }
tstring stl_str() const { return tstring( c_str(), size() ); }
DWORD size() const { return length_; }
DWORD & size() { return length_; }
TCHAR const * begin() const { return c_str(); }
TCHAR const * end () const { return c_str() + size(); }
void setString( TCHAR const * const newString ) { string_ = newString; }
void setLength( DWORD const newLength ) { length_ = newLength; }
private:
TCHAR const * string_;
DWORD length_;
};
////////////////////////////////////////////////////////////////////////////////
//
// RegistryKey
// -----------
//
// A light RAII wrapper for a registry key (handle).
//
////////////////////////////////////////////////////////////////////////////////
class RegistryKey
{
public:
RegistryKey( char const * subKeyName, HKEY rootKey = HKEY_LOCAL_MACHINE, REGSAM desiredAccessRights = 0 );
RegistryKey( wchar_t const * subKeyName, HKEY rootKey = HKEY_LOCAL_MACHINE, REGSAM desiredAccessRights = 0 );
RegistryKey( RegistryKey const & sourceKey ) : hKey_( duplicateHandle( *sourceKey ) ) {}
~RegistryKey() { close(); }
RegistryKey & operator=( RegistryKey const & sourceKey );
HKEY operator*() const { return hKey_; }
typedef void (RegistryKey::*unspecified_bool_type)();
operator unspecified_bool_type() const { return hKey_ ? &RegistryKey::close : 0; }
public:
static size_t const maximumRegistryKeyNameLength = 255;
private:
HKEY duplicateHandle( HKEY const sourceKey );
void close();
private:
HKEY hKey_;
};
////////////////////////////////////////////////////////////////////////////////
//
// SubKeys
// -------
//
// A wrapper around a registry key (handle) that tries to provide access to its
// subkeys through an STL (random-access) container like interface.
//
////////////////////////////////////////////////////////////////////////////////
//
// (todo) Add (debug) RegNotifyChangeKeyValue() notification to check if someone
// is modifying the key(s) while they are being read.
//
////////////////////////////////////////////////////////////////////////////////
class SubKeys
{
public:
typedef WinString const value_type;
typedef DWORD difference_type;
typedef DWORD size_type;
typedef value_type * const_pointer;
typedef value_type & const_reference;
class const_iterator;
public:
SubKeys( RegistryKey const & parentKey );
SubKeys( TCHAR const * subKeyName, HKEY rootKey = HKEY_LOCAL_MACHINE );
public: // Sequence interface.
bool empty() const { return size() == 0 ; }
size_type size () const { return numberOfSubKeys_; }
const_iterator begin() const;
const_iterator end () const;
// "Not exactly" standard conformant.
const_iterator operator[]( difference_type subKeyIndex ) const;
public: // Utility interface.
RegistryKey const & parentKey() const { return parentKey_; }
// The following might perform slightly better/produce smaller code than the STL counterparts.
const_iterator find( value_type subKeyName ) const;
const_iterator find( TCHAR const * subKeyName ) const;
// Feeds the undereferenced iterator to the functor so that it can use the utility interface.
template<class Functor>
void for_each( Functor & functor ) const
{
const_iterator pSubKey( begin() );
while( pSubKey.currentIndex() < size() )
{
functor( pSubKey );
++pSubKey;
}
}
private:
RegistryKey parentKey_;
difference_type numberOfSubKeys_;
};
////////////////////////////////////////////////////////////////////////////////
//
// SubKeys::const_iterator
// -----------------------
//
////////////////////////////////////////////////////////////////////////////////
class SubKeys::const_iterator : public std::iterator<std::random_access_iterator_tag, SubKeys::value_type, SubKeys::difference_type>
{
public: // Random access iterator interface.
const_iterator( HKEY hParentKey, unsigned int startingSubKeyIndex = 0, bool readKeyName = true );
const_iterator( const_iterator const & );
const_iterator & operator++() { goToIndex( ++currentSubKeyIndex_ ); return *this; }
const_iterator & operator--() { goToIndex( --currentSubKeyIndex_ ); return *this; }
const_iterator & operator+=( difference_type const offset ) { goToIndex( currentSubKeyIndex_ + offset ); return *this; }
const_iterator & operator-=( difference_type const offset ) { goToIndex( currentSubKeyIndex_ - offset ); return *this; }
const_iterator operator+ ( difference_type const offset ) const { return const_iterator( parentKey_, currentSubKeyIndex_ + offset ); }
const_iterator operator- ( difference_type const offset ) const { return const_iterator( parentKey_, currentSubKeyIndex_ - offset ); }
const_iterator & operator= ( const_iterator const & );
value_type & operator* () const { assert( currentSubKeyName_.size() ); return currentSubKeyName_; }
value_type * operator->() const { return &**this; }
bool operator==( const_iterator const & other ) const { return currentSubKeyIndex_ == other.currentSubKeyIndex_ && parentKey_ == other.parentKey_; }
bool operator!=( const_iterator const & other ) const { return !( *this == other ); }
bool operator< ( const_iterator const & other ) const { assert( ( parentKey_ == other.parentKey_ ) && "Mismatched iterators" ); return currentSubKeyIndex_ < other.currentSubKeyIndex_; }
// "Not exactly" standard conformant.
const_iterator operator[]( difference_type const offset ) const { return *this + offset; }
public: // Utility interface.
distance_type currentIndex() const { return currentSubKeyIndex_; }
HKEY const & parentKey () const { return parentKey_; }
void reset () { goToIndex( 0 ); }
private:
void goToIndex( unsigned int keyIndex );
private:
HKEY parentKey_ ;
distance_type currentSubKeyIndex_;
WinString currentSubKeyName_ ; // Not using value_type to enable the assignment operator.
// (todo) think of a better solution that will not "explode" under Unicode.
TCHAR nameBuffer_[ RegistryKey::maximumRegistryKeyNameLength ];
};
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.