#include "Registry.hpp"
#include "debugMacros.hpp"
//************************************
// Method: SubKeys
// FullName: SubKeys::SubKeys
// Access: public
//************************************
SubKeys::SubKeys( TCHAR const * const subKeyName, HKEY const rootKey )
:
parentKey_( subKeyName, rootKey, KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE )
{
VERIFY( ::RegQueryInfoKey( *parentKey_, NULL, NULL, NULL, &numberOfSubKeys_, NULL, NULL, NULL, NULL, NULL, NULL, NULL ) == ERROR_SUCCESS );
}
//************************************
// Method: SubKeys
// FullName: SubKeys::SubKeys
// Access: public
//************************************
SubKeys::SubKeys( RegistryKey const & parentKey )
:
parentKey_( parentKey )
{
VERIFY( ::RegQueryInfoKey( *parentKey_, NULL, NULL, NULL, &numberOfSubKeys_, NULL, NULL, NULL, NULL, NULL, NULL, NULL ) == ERROR_SUCCESS );
}
//************************************
// Method: find
// FullName: SubKeys::find
// Access: public
//************************************
SubKeys::const_iterator SubKeys::find( TCHAR const * const subKeyName ) const
{
return find( value_type( subKeyName, std::strlen( subKeyName ) ) );
}
//************************************
// Method: find
// FullName: SubKeys::find
// Access: public
//************************************
SubKeys::const_iterator SubKeys::find( value_type subKeyName ) const
{
assert( !empty() );
const_iterator pSubKey( begin() );
while( pSubKey.currentIndex() < size() )
{
if ( ( subKeyName.size() == pSubKey->size() ) && ( std::memcmp( subKeyName.c_str(), pSubKey->c_str(), subKeyName.size() ) == 0 ) )
break;
++pSubKey;
}
return pSubKey;
}
//************************************
// Method: begin
// FullName: SubKeys::begin
// Access: public
//************************************
SubKeys::const_iterator SubKeys::begin() const
{
assert( !empty() );
return const_iterator( *parentKey_ );
}
//************************************
// Method: end
// FullName: SubKeys::end
// Access: public
//************************************
SubKeys::const_iterator SubKeys::end() const
{
return const_iterator( *parentKey_, numberOfSubKeys_, false );
}
//************************************
// Method: operator[]
// FullName: SubKeys::operator[]
// Access: public
//************************************
SubKeys::const_iterator SubKeys::operator[]( difference_type const subKeyIndex ) const
{
assert( subKeyIndex < size() );
return const_iterator( *parentKey_, subKeyIndex );
}
//************************************
// Method: goToIndex
// FullName: SubKeys::const_iterator::goToIndex
// Access: private
//************************************
__declspec( noinline )
void SubKeys::const_iterator::goToIndex( unsigned int const keyIndex )
{
currentSubKeyName_.setLength( sizeof( nameBuffer_ ) );
LONG const result( ::RegEnumKeyEx( parentKey_, currentSubKeyIndex_ = keyIndex, nameBuffer_, ¤tSubKeyName_.size(), NULL, NULL, NULL, NULL ) );
// ERROR_NO_MORE_ITEMS is tolerated to enable incrementing to the "end"
// iterator (one past last) without an assertion failure (the other solution
// would be to implement lazy value retrieving (instead of immediately in
// operator ++).
// (todo) add better error checking and handling here.
assert( ( result == ERROR_SUCCESS ) || ( result == ERROR_NO_MORE_ITEMS ) );
result;
}
//************************************
// Method: const_iterator
// FullName: SubKeys::const_iterator::const_iterator
// Access: public
//************************************
SubKeys::const_iterator::const_iterator( HKEY const parentKey, unsigned int const startingSubKeyIndex, bool const readKeyName )
:
parentKey_ ( parentKey ),
currentSubKeyName_( nameBuffer_, 0 )
{
assert( parentKey );
if ( readKeyName )
goToIndex( startingSubKeyIndex );
else
currentSubKeyIndex_ = startingSubKeyIndex;
}
//************************************
// Method: const_iterator
// FullName: SubKeys::const_iterator::const_iterator
// Access: public
//************************************
SubKeys::const_iterator::const_iterator( SubKeys::const_iterator const & source )
{
*this = source;
}
//************************************
// Method: operator=
// FullName: SubKeys::const_iterator::operator=
// Access: public
//************************************
SubKeys::const_iterator & SubKeys::const_iterator::operator=( SubKeys::const_iterator const & source )
{
std::memcpy( this, &source, sizeof( source ) - ( sizeof( nameBuffer_ ) - source.currentSubKeyName_.size() - 1 ) );
(*this).currentSubKeyName_.setString( (*this).nameBuffer_ );
return *this;
}
//************************************
// Method: duplicateHandle
// FullName: RegistryKey::duplicateHandle
// Access: private
//************************************
HKEY RegistryKey::duplicateHandle( HKEY const sourceKey )
{
HKEY tempHandle;
VERIFY( ( ::RegOpenKeyEx( sourceKey, NULL, 0, 0, &tempHandle ) == ERROR_SUCCESS ) || ( tempHandle == NULL ) );
return tempHandle;
}
//************************************
// Method: close
// FullName: RegistryKey::close
// Access: private
//************************************
void RegistryKey::close()
{
VERIFY( ( ::RegCloseKey( hKey_ ) == ERROR_SUCCESS ) || !*this );
}
//************************************
// Method: operator=
// FullName: RegistryKey::operator=
// Access: public
//************************************
RegistryKey & RegistryKey::operator=( RegistryKey const & sourceKey )
{
close();
hKey_ = duplicateHandle( *sourceKey );
return *this;
}
//************************************
// Method: RegistryKey
// FullName: RegistryKey::RegistryKey
// Access: public
//************************************
// (todo) Unify the following two overloads more intelligently.
//************************************
RegistryKey::RegistryKey( char const * const subKeyName, HKEY const rootKey, REGSAM const desiredAccessRights )
{
if ( desiredAccessRights )
VERIFY( ::RegOpenKeyEx( rootKey, subKeyName, 0, desiredAccessRights, &hKey_ ) == ERROR_SUCCESS );
else
VERIFY( ::RegOpenKey ( rootKey, subKeyName, &hKey_ ) == ERROR_SUCCESS );
}
RegistryKey::RegistryKey( wchar_t const * const subKeyName, HKEY const rootKey, REGSAM const desiredAccessRights )
{
if ( desiredAccessRights )
VERIFY( ::RegOpenKeyExW( rootKey, subKeyName, 0, desiredAccessRights, &hKey_ ) == ERROR_SUCCESS );
else
VERIFY( ::RegOpenKeyW ( rootKey, subKeyName, &hKey_ ) == ERROR_SUCCESS );
}