Click here to Skip to main content
15,886,362 members
Articles / Desktop Programming / MFC

Simple registry class Enhancement

Rate me:
Please Sign up or sign in to vote.
3.50/5 (10 votes)
15 May 2002CPOL5 min read 82.5K   2.5K   17  
A simple class which simplifies working with registry values and history items lists.
/********************************************************************
  created:    2001/11/07
  created:    7:11:2001   12:50
  filename:   d:\My Projects\Own\Add-on\ToDoCached\regRegistryEx.cpp
  file path:  d:\My Projects\Own\Add-on\ToDoCached
  file base:  regRegistryEx
  file ext:   cpp
  author:     Alex Kucherenko

  purpose:    
*********************************************************************/

#include "stdafx.h"
#include "regRegistryEx.h"

#ifdef _DEBUG
# undef THIS_FILE
static char THIS_FILE[]=__FILE__;
# define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////////
// constructor 

CRegistryEx::CRegistryEx( const HKEY hKey, const string &startPoint ) 
  : m_hInitKey( hKey )
  , m_strInitPoint( startPoint )
{
};

/////////////////////////////////////////////////////////////////////////
// destructor

CRegistryEx::~CRegistryEx()
{
  RefreshRegistry();
  m_mapValues.clear();
  Close();
};

/////////////////////////////////////////////////////////////////////////
// function read all values from registry

void CRegistryEx::RefreshContents( void ) throw( string )
{
  // set default values into registryu class cache
  SetDefaults();

  LONG status = Open( m_hInitKey, m_strInitPoint.c_str() );

  if( status != ERROR_SUCCESS )
    RefreshRegistry();
  else
  {
    char  buffer[ MAX_STRING_LENGTH ];
    BYTE  databuf[ MAX_STRING_LENGTH ];

    DWORD dwIndex = 0;
    DWORD dwType = 0;
    DWORD dwSize = sizeof( buffer );
    DWORD dwDatSize = sizeof( databuf );
    
    // Enum All subkeys
    do
    {
      status = ::RegEnumKeyEx( m_hKey, dwIndex, buffer, &dwSize, NULL, NULL, NULL, NULL );
      if( status != ERROR_SUCCESS ) break;

      m_qSubKeys.push( strlwr( buffer ) );
      
      dwSize = sizeof( buffer );
      dwIndex++;
    } while( 1 );

    // Enum All Values in subkeys
    dwIndex = 0;
    dwSize = sizeof( buffer );
    string subKey;
    string varName, varData;
    do
    {
      status = ::RegEnumValue( m_hKey, dwIndex, buffer, &dwSize, NULL, &dwType, databuf, &dwDatSize );

      dwSize = sizeof( buffer );
      dwDatSize = sizeof( databuf );

      if( status != ERROR_SUCCESS )
      {
        if( m_qSubKeys.empty() ) break;
        subKey = m_strInitPoint + "\\" + m_qSubKeys.front();
        
        Close();
        status = Open( m_hInitKey, subKey.c_str() );
        if( status != ERROR_SUCCESS ) break;
        
        subKey = m_qSubKeys.front();
        m_qSubKeys.pop();
        dwIndex = 0;
        continue;
      };
      
      varName = subKey + "\\" + strlwr( buffer ); 
      if( dwType == REG_SZ ) varData = (char *)databuf; 
      else continue;

      m_mapValues[ varName ] = varData;
      dwIndex++;
    } while( 1 );

    Close();
    Open( m_hInitKey, m_strInitPoint.c_str( ) );
  }
};

/////////////////////////////////////////////////////////////////////////
// Function set value to registry

void CRegistryEx::RefreshRegistry( void ) throw( string )
{
  LONG state = Create( m_hInitKey, m_strInitPoint.c_str() );
  if( state != ERROR_SUCCESS ) throw string( "Error! Cannot create registry key!" );

  TRegIter i;
  std::stack<string>  stSubKeys;
  string temp, subKey;

  stSubKeys.push( "::" );
  
  for( i = m_mapValues.begin(); i != m_mapValues.end(); i++ )
  {
    string first = i->first;
    string::size_type pos = first.find( "\\" );
    
    if( pos != first.npos )
    {
      temp = first.substr( 0, pos );
      
      if( temp.empty() || temp == stSubKeys.top() )
      { 
        if( !temp.empty() ) stSubKeys.push( temp );
        subKey = first.substr( pos+1 );
        SetValue( i->second.c_str( ), subKey.c_str( ) );
      }
      else
      {
        Close();
        subKey = m_strInitPoint + "\\" + temp;
        stSubKeys.push( temp );
        
        state = Create( m_hInitKey, subKey.c_str( ) );
        if( state != ERROR_SUCCESS ) throw string( "Error! Cannot create registry key!" );
        
        subKey = first.substr( pos+1 );
        SetValue( i->second.c_str( ), subKey.c_str( ) );
      }

    }
  }

  Close();
  Open( m_hInitKey, m_strInitPoint.c_str( ) );
};

/////////////////////////////////////////////////////////////////////////
// function return value by param name

LONG CRegistryEx::GetValueByName(IN const string &name,OUT string &result)
{
	result = m_mapValues[ CorrentRegistryPath( name ) ];
  return 0;
}

//////////////////////////////////////////////////////////////////////////
// function return pointer to value string 

LONG CRegistryEx::GetValueByName(IN const char *czName,OUT char *czResult)
{
	czResult = const_cast<char *>( m_mapValues[ CorrentRegistryPath( string( czName ) ) ].c_str() );
  return 0;
}

//////////////////////////////////////////////////////////////////////////
// function set output value to lResult

LONG CRegistryEx::GetValueByName(IN const string &name,OUT long &lResult)
{
	lResult = atol( m_mapValues[ CorrentRegistryPath( name ) ].c_str() );
  return 0;
}

//////////////////////////////////////////////////////////////////////////
// function set output value to lResult

LONG CRegistryEx::GetValueByName(IN const char *czName,OUT long &lResult)
{
	lResult = atol( m_mapValues[ CorrentRegistryPath( string( czName ) ) ].c_str() );
  return 0;
}

/////////////////////////////////////////////////////////////////////////
// Set value in registry

void CRegistryEx::SetValueByName(IN const string &name,IN const string &value)
{
	m_mapValues[ CorrentRegistryPath( name ) ] = value;
}

//////////////////////////////////////////////////////////////////////////
// Set value in registry

void CRegistryEx::SetValueByName(IN const char *czName,IN const char *czValue)
{
	m_mapValues[ CorrentRegistryPath( string( czName ) ) ] = czValue;
}

//////////////////////////////////////////////////////////////////////////
// Set value in registry

void CRegistryEx::SetValueByName(IN const string &name,IN long lValue)
{
  char buffer[ 32 ];
  ltoa( lValue, buffer, 10 );
  m_mapValues[ CorrentRegistryPath( name ) ] = buffer;
}

//////////////////////////////////////////////////////////////////////////
// Set value in registry

void CRegistryEx::SetValueByName(IN const char *czName,IN long lValue)
{
  char buffer[ 32 ];
  ltoa( lValue, buffer, 10 );
  m_mapValues[ CorrentRegistryPath( string( czName ) ) ] = buffer;
}

/////////////////////////////////////////////////////////////////////////
// function return array of registry values according to input template

LONG CRegistryEx::GetArrayByTemplate(IN const string &templ,OUT TStrArray &arrResult)
{
  return GetArrayByTemplate( templ.c_str(), arrResult );
}

//////////////////////////////////////////////////////////////////////////
// Function return values according to input template

LONG CRegistryEx::GetArrayByTemplate(IN const char *czTempl,OUT TStrArray &arrResult)
{
  TRegIter  i;
  DWORD     dwValue = 0;
  
  for( i = m_mapValues.begin(); i != m_mapValues.end(); i++ )
  {
    int ret = sscanf( i->first.c_str( ), czTempl, &dwValue );
    if( ret == 1 ) arrResult.push_back( i->second );
  }
  
  return 0;
}

//////////////////////////////////////////////////////////////////////////
// Return array of values according to input array of registry pathes

LONG CRegistryEx::GetArrayByArray(IN const TStrArray &arrNames,OUT TStrArray &arrResult)
{
  for( UINT i=0; i<arrNames.size( ); i++ )
    arrResult.push_back( m_mapValues[ CorrentRegistryPath( arrNames[i] ) ] );
  
  return 0;
}

/////////////////////////////////////////////////////////////////////////
// set values of regitry pathes according to template

void CRegistryEx::SetValueByTemplate( const string &templ, const TStrArray &arrValue )
{
  char buffer[ MAX_STRING_LENGTH ];

  for( UINT k=0; k<arrValue.size(); k++ )
  {
    _snprintf( buffer, sizeof(buffer), templ.c_str(), k+1 );
    m_mapValues[ CorrentRegistryPath( string( buffer ) ) ] = arrValue[ k ];
  }
};

//////////////////////////////////////////////////////////////////////////
// Function set default values to params of registry 

void CRegistryEx::SetDefaults( void )
{
  /* E_NOTIMPL - empty function */
}

/////////////////////////////////////////////////////////////////////////
// Function set multiple params to new values

void CRegistryEx::SetArrayByArray( const TStrArray &arrNames, const TStrArray &arrValues ) throw( string )
{
  if( arrNames.size() != arrValues.size() ) 
    throw string( "Size of values and params arrays not equel" );
  
  for( UINT i = 0; i<arrNames.size( ); i++ )
    m_mapValues[ CorrentRegistryPath( arrNames[ i ] ) ] = arrValues[ i ];
};

//////////////////////////////////////////////////////////////////////////
// Delete param from registry

void CRegistryEx::DeleteByName( const string &name )
{
  TRegIter i = m_mapValues.find( name );
  
  if( i != m_mapValues.end() )
  {
    m_mapValues.erase( i );
    string::size_type pos = name.find( "\\" );
    string newPoint = m_strInitPoint + "\\" + name.substr( 0, pos );
    Close();

    LONG lRes = Open( m_hInitKey, newPoint.c_str() );

    if( lRes == ERROR_SUCCESS )
      DeleteValue( name.substr( pos+1 ).c_str( ) );
  }
};

//////////////////////////////////////////////////////////////////////////
// Delete values from registry according to template

void CRegistryEx::DeleteByTemplate( const string &templ )
{
  TStrArray temp;
  GetNamesByTemplate( templ, temp );
  DeleteByArray( temp );
};

//////////////////////////////////////////////////////////////////////////
// Delete values from registry according to array of registry pathes

void CRegistryEx::DeleteByArray( const TStrArray &array )
{
  TStrArray::const_iterator j;
  for( j = array.begin(); j != array.end(); j++ )
    DeleteByName( *j );
};

//////////////////////////////////////////////////////////////////////////
// Function return array of registry names according to template

LONG CRegistryEx::GetNamesByTemplate(IN const string &templ,OUT TStrArray &arrResult)
{
  return GetNamesByTemplate( templ.c_str(), arrResult );
}

//////////////////////////////////////////////////////////////////////////
// Function return array of registry names according to template

LONG CRegistryEx::GetNamesByTemplate(IN const char *czTempl,OUT TStrArray &arrResult)
{
  DWORD     dwValue = 0;
  
  for( TRegIter i = m_mapValues.begin(); i != m_mapValues.end(); i++ )
  {
    int ret = sscanf( i->first.c_str( ), czTempl, &dwValue );
    if( ret == 1 ) arrResult.push_back( i->first );
  }

  return 0;
}

//////////////////////////////////////////////////////////////////////////
// Function set registry key/values according to template and input array 
// of values. 

void CRegistryEx::SetValueByTemplate( IN const char *czTempl, IN const TStrArray &arrValue )
{
  string temp = czTempl;
  SetValueByTemplate( temp, arrValue );
};

//////////////////////////////////////////////////////////////////////////
// Delete value from registry

void CRegistryEx::DeleteByName( IN const char *czName )
{
  string temp = czName;
  DeleteByName( temp );
};

//////////////////////////////////////////////////////////////////////////
// Try to resolve variable path before using it

string &CRegistryEx::CorrentRegistryPath( IN const string &path )
{
  m_strTmpPath = path;
  TRegMap::iterator iter = m_mapValues.find( path );
  
  if( iter == m_mapValues.end() )
  {
    iter = m_mapValues.find( "\\" + m_strTmpPath );
    
    if( iter != m_mapValues.end() ) 
      m_strTmpPath = "\\" + path;
    else 
      if( m_strTmpPath.find( "\\" ) == string::npos ) 
        m_strTmpPath = "\\" + path;
  }

  return m_strTmpPath;
}


//:> end of file

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.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
CEO ArtfulBits Inc.
Ukraine Ukraine
Name:Kucherenko Oleksandr

Born:September 20, 1979

Platforms: Win32, Linux; - well known and MS-DOS; Win16; OS/2 - old time not touched;

Hardware: IBM PC

Programming Languages: Assembler (for Intel 80386); Borland C/C++; Borland Pascal; Object Pascal; Borland C++Builder; Delphi; Perl; Java; Visual C++; Visual J++; UML; XML/XSL; C#; VB.NET; T-SQL; PL/SQL; and etc.

Development Environments: MS Visual Studio 2001-2008; MS Visual C++; Borland Delphi; Borland C++Builder; C/C++ any; Rational Rose; GDPro; Together and etc.

Libraries: STL, ATL, WTL, MFC, NuMega Driver Works, VCL; .NET 1.0, 1.1, 2.0, 3.5; and etc.

Technologies: Client/Server; COM; DirectX; DirectX Media; BDE; HTML/DHTML; ActiveX; Java Servlets; DCOM; COM+; ADO; CORBA; .NET; Windows Forms; GDI/GDI+; and etc.

Application Skills: Databases - design and maintain, support, programming; GUI Design; System Programming, Security; Business Software Development. Win/Web Services development and etc.

Comments and Discussions