//************************************************************
//*
//* RegSettings.cpp
//*
//* RegSettings class implementation
//*
//* DESCRIPTION:
//* One MFC CObject derived class to implement a simple
//* interface for storing app settings into registry.
//*
//* ASSUMES:
//* Only MFC and an average coder :-)
//*
//* AUTHOR: T1TAN <t1tan@cmar-net.org>
//*
//* COPYLEFT:
//* Copyleft (C) T1TAN 2004 - 3827
//* Copyleft (C) SprdSoft Inc.2004 - 3827
//* FREE for (ab)use in any way except selling the code.
//* Leave the headers be.
//*
//* VERSIONS:
//* VERSION AUTHOR DATE NOTES
//* ------- ------ ---- -----
//* 1.0 T1TAN 18/10/2004 initial version
//*
//*
//* OTHER:
//* Em well, nothing yet. Though, this is only a basic
//* implementation, and there is MUCH that could be
//* implemented, I believe this is a good start..(-:
//*
//************************************************************
#include "stdafx.h"
#include "RegSettings.h"
#include <shlwapi.h> // for SHDeleteKey
#pragma comment( lib, "shlwapi.lib" )
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
/*
The one and only contructor.
If you want to use flushing, set it here
*/
CRegSettings::CRegSettings( BOOL bUseFlushing /*= FALSE*/ )
{
m_szAppName = _T("");
m_szCompanyName = _T("");
m_bUseFlushing = bUseFlushing;
}
CRegSettings::~CRegSettings()
{
}
BOOL CRegSettings::GetHKEY( LPCTSTR szKey, PHKEY hKey, BOOL bRead /*= FALSE*/ )
{
CString clean_key = CleanKeyName( szKey );
// we're always opening a key like this one
// (assuming the company name is "SprdSoft"
// and program is "Bullocks")
//
// HKCU\Software\SprdSoft\Bullocks\Key_You_Want\Its_Subkey\ETC
//
CString the_key = _T("Software");
/*
You do need to use AT LEAST one of company/app name
*/
if ( m_szCompanyName.IsEmpty() == TRUE && m_szAppName.IsEmpty() == TRUE )
{ // so you can extract it by CRegSettings::GetLastErrorText()
SetLastErrorEx(ERROR_INVALID_DATA, NULL);
return FALSE;
}
/*
By checking each one of these (company/app name), we can make
the thing work if you want to use only one of them.
*/
if ( m_szCompanyName.IsEmpty() == FALSE )
{
the_key += _T("\\");
the_key += m_szCompanyName;
}
if ( m_szAppName.IsEmpty() == FALSE )
{
the_key += _T("\\");
the_key += m_szAppName;
}
the_key += _T("\\");
the_key += clean_key;
LONG result = 0;
if ( bRead == TRUE )
{ // don't create it, just open existing
result = RegOpenKeyEx(
HKEY_CURRENT_USER,
the_key,
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
hKey );
}
else
{ // open for writing, so create if it doesn't exist
result = RegCreateKeyEx(
HKEY_CURRENT_USER,
the_key,
0, // reserved
NULL, // class
REG_OPTION_NON_VOLATILE, // default
KEY_ALL_ACCESS, // desired access
NULL, // security attributes
hKey, // result
NULL );
}
if ( result == ERROR_SUCCESS )
return TRUE;
else
{
SetLastErrorEx(result, NULL);
return FALSE;
}
}
void CRegSettings::CloseHKEY( HKEY hKey )
{
if ( m_bUseFlushing == TRUE )
RegFlushKey( hKey );
RegCloseKey( hKey );
}
/**************************************************
We want to have a clear key name, for example:
SprdSoft\\IronMaiden\\Eddie
A key name like this one:
\\SprdSoft\\BlackSabbath\\PlanetCaravan
would be illegal because of the slash thingie
at the beggining.
**************************************************/
CString CRegSettings::CleanKeyName( LPCTSTR szKey )
{
CString mod;
mod = szKey;
// remove extra spaces, tabs and whatever
mod.TrimLeft();
mod.TrimRight();
// enables us to use it in two ways:
// Write( "Settings\\Aerodynamics\\Pilot", "Moo", "Goo" );
// OR
// Write( "Settings/Aerodynamics/Pilot", "Moo", "Goo" );
//
mod.Replace( _T('/'), _T('\\') );
// we cannot have these double slashes
// so just in case..
mod.Replace( _T("\\\\"), _T("\\") );
// cannot start or end with this, or we'll get an error
mod.TrimLeft(_T('\\'));
mod.TrimRight(_T('\\'));
return mod;
}
/*
One of the ways to get a nice flashing and also
VERY amusing MessageBoxes
*/
CString CRegSettings::GetLastErrorText()
{
LONG err_code = GetLastError();
char txt[2048];
FormatMessage(
FORMAT_MESSAGE_FROM_SYSTEM,
NULL, err_code, 0, txt, 2048, NULL );
CString sz(txt);
return sz;
}
/*
Deleting a key seemed simple, but(t)...
IMPORTANT: 1. If you haven't used app name, you MUST use
bDeleteCompany when deleting...
2. If you haven't used company name, and you
do set bDeleteCompany to TRUE, it is ignored
*/
BOOL CRegSettings::DeleteAll( BOOL bDeleteCompany /*= FALSE*/ )
{
// first check that we have at least one of these...
if ( m_szCompanyName.IsEmpty() == TRUE && m_szAppName.IsEmpty() == TRUE )
{
SetLastErrorEx(ERROR_INVALID_DATA, NULL);
return FALSE;
}
HKEY hKey;
CString the_key = "";
the_key = _T("Software");
// if the company name is not empty...
if ( m_szCompanyName.IsEmpty() == FALSE )
{
if ( bDeleteCompany == TRUE )
{ // we need to delete the entire company subtree
LONG res = RegOpenKeyEx(
HKEY_CURRENT_USER,
the_key,
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
&hKey );
if ( res != ERROR_SUCCESS )
return FALSE;
if ( SHDeleteKey( hKey, m_szCompanyName ) == ERROR_SUCCESS )
return TRUE;
else
return FALSE;
}
else
{ // just add it up..
the_key += "\\";
the_key += m_szCompanyName;
}
}
if ( m_szAppName.IsEmpty() == FALSE )
{ // now we're opening like this:
// HKCU\Software\Company Inc
LONG res = RegOpenKeyEx(
HKEY_CURRENT_USER,
the_key,
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
&hKey );
if ( res != ERROR_SUCCESS )
return FALSE;
if ( SHDeleteKey( hKey, m_szAppName ) == ERROR_SUCCESS )
return TRUE;
else
return FALSE;
}
return FALSE;
}
///////////////////////////////////////////////////////////////////////
// And now for something completely different...
// Id est: a bunch of Write(..) and Read(..) overloads
// to support common data types in MFC
//
// They are all quite simple, and quite the same, with exception of
// those related to REG_BINARY and REG_SZ data. The only difference
// is that we need to calculate their size in a different manner.
// Check these out for more info:
// BOOL Write( ..., ..., LPCTSTR value );
// BOOL Write( ..., ..., const LPVOID value, UINT size );
// BOOL Read( ..., ..., LPTSTR value, ULONG& size );
// BOOL Read( ..., ..., LPVOID value, ULONG& size );
///////////////////////////////////////////////////////////////////////
BOOL CRegSettings::Write( LPCTSTR szKey, LPCTSTR szName, UCHAR value )
{
HKEY hKey;
if ( GetHKEY( szKey, &hKey ) == FALSE )
return FALSE;
LONG result =
RegSetValueEx( hKey, szName, NULL, REG_SZ, (UCHAR*)&value, sizeof(UCHAR) );
CloseHKEY( hKey );
if ( result == ERROR_SUCCESS )
return TRUE;
else
{
SetLastErrorEx(result, NULL);
return FALSE;
}
}
BOOL CRegSettings::Write( LPCTSTR szKey, LPCTSTR szName, char value )
{
HKEY hKey;
if ( GetHKEY( szKey, &hKey ) == FALSE )
return FALSE;
LONG result =
RegSetValueEx( hKey, szName, NULL, REG_SZ, (UCHAR*)&value, sizeof(char) );
CloseHKEY( hKey );
if ( result == ERROR_SUCCESS )
return TRUE;
else
{
SetLastErrorEx(result, NULL);
return FALSE;
}
}
BOOL CRegSettings::Write( LPCTSTR szKey, LPCTSTR szName, USHORT value )
{
HKEY hKey;
if ( GetHKEY( szKey, &hKey ) == FALSE )
return FALSE;
LONG result =
RegSetValueEx( hKey, szName, 0, REG_SZ, (UCHAR*)&value, sizeof(USHORT) );
CloseHKEY( hKey );
if ( result == ERROR_SUCCESS )
return TRUE;
else
{
SetLastErrorEx(result, NULL);
return FALSE;
}
}
BOOL CRegSettings::Write( LPCTSTR szKey, LPCTSTR szName, short value )
{
HKEY hKey;
if ( GetHKEY( szKey, &hKey ) == FALSE )
return FALSE;
LONG result =
RegSetValueEx( hKey, szName, 0, REG_SZ, (UCHAR*)&value, sizeof(short) );
CloseHKEY( hKey );
if ( result == ERROR_SUCCESS )
return TRUE;
else
{
SetLastErrorEx(result, NULL);
return FALSE;
}
}
BOOL CRegSettings::Write( LPCTSTR szKey, LPCTSTR szName, UINT value )
{
HKEY hKey;
if ( GetHKEY( szKey, &hKey ) == FALSE )
return FALSE;
LONG result =
RegSetValueEx( hKey, szName, 0, REG_DWORD, (LPBYTE)&value, sizeof(UINT) );
CloseHKEY( hKey );
if ( result == ERROR_SUCCESS )
return TRUE;
else
{
SetLastErrorEx(result, NULL);
return FALSE;
}
}
BOOL CRegSettings::Write( LPCTSTR szKey, LPCTSTR szName, int value )
{
HKEY hKey;
if ( GetHKEY( szKey, &hKey ) == FALSE )
return FALSE;
LONG result =
RegSetValueEx( hKey, szName, 0, REG_DWORD, (LPBYTE)&value, sizeof(int) );
CloseHKEY( hKey );
if ( result == ERROR_SUCCESS )
return TRUE;
else
{
SetLastErrorEx(result, NULL);
return FALSE;
}
}
BOOL CRegSettings::Write( LPCTSTR szKey, LPCTSTR szName, ULONG value )
{
HKEY hKey;
if ( GetHKEY( szKey, &hKey ) == FALSE )
return FALSE;
LONG result =
RegSetValueEx( hKey, szName, 0, REG_DWORD, (LPBYTE)&value, sizeof(ULONG) );
CloseHKEY( hKey );
if ( result == ERROR_SUCCESS )
return TRUE;
else
{
SetLastErrorEx(result, NULL);
return FALSE;
}
}
BOOL CRegSettings::Write( LPCTSTR szKey, LPCTSTR szName, long value )
{
HKEY hKey;
if ( GetHKEY( szKey, &hKey ) == FALSE )
return FALSE;
LONG result =
RegSetValueEx( hKey, szName, 0, REG_DWORD, (LPBYTE)&value, sizeof(long) );
CloseHKEY( hKey );
if ( result == ERROR_SUCCESS )
return TRUE;
else
{
SetLastErrorEx(result, NULL);
return FALSE;
}
}
BOOL CRegSettings::Write( LPCTSTR szKey, LPCTSTR szName, float value )
{
HKEY hKey;
if ( GetHKEY( szKey, &hKey ) == FALSE )
return FALSE;
LONG result =
RegSetValueEx( hKey, szName, 0, REG_DWORD, (LPBYTE)&value, sizeof(float) );
CloseHKEY( hKey );
if ( result == ERROR_SUCCESS )
return TRUE;
else
{
SetLastErrorEx(result, NULL);
return FALSE;
}
}
BOOL CRegSettings::Write( LPCTSTR szKey, LPCTSTR szName, double value )
{
HKEY hKey;
if ( GetHKEY( szKey, &hKey ) == FALSE )
return FALSE;
LONG result =
RegSetValueEx( hKey, szName, 0, REG_BINARY, (LPBYTE)&value, sizeof(double) );
CloseHKEY( hKey );
if ( result == ERROR_SUCCESS )
return TRUE;
else
{
SetLastErrorEx(result, NULL);
return FALSE;
}
}
BOOL CRegSettings::Write( LPCTSTR szKey, LPCTSTR szName, LPCTSTR value )
{
HKEY hKey;
if ( GetHKEY( szKey, &hKey ) == FALSE )
return FALSE;
// according to Platform SDK
// we need string length + 1 for the Terminator II (the liquid one)
int length = _tcslen( value );
length += 1;
LONG result =
RegSetValueEx( hKey, szName, 0, REG_SZ, (LPBYTE)value, length );
CloseHKEY( hKey );
if ( result == ERROR_SUCCESS )
return TRUE;
else
{
SetLastErrorEx(result, NULL);
return FALSE;
}
}
/*
The only write function in desperate need of "size" variable.
*/
BOOL CRegSettings::Write( LPCTSTR szKey, LPCTSTR szName, LPVOID value, UINT size )
{
HKEY hKey;
if ( GetHKEY( szKey, &hKey ) == FALSE )
return FALSE;
LONG result =
RegSetValueEx( hKey, szName, 0, REG_BINARY, (LPBYTE)value, size );
CloseHKEY( hKey );
if ( result == ERROR_SUCCESS )
return TRUE;
else
{
SetLastErrorEx(result, NULL);
return FALSE;
}
}
BOOL CRegSettings::Read( LPCTSTR szKey, LPCTSTR szName, UCHAR& value )
{
HKEY hKey;
if ( GetHKEY( szKey, &hKey, TRUE ) == FALSE )
return FALSE;
ULONG size = sizeof(UCHAR);
LONG result =
RegQueryValueEx( hKey, szName, 0, NULL, (LPBYTE)&value, &size );
CloseHKEY( hKey );
if ( result == ERROR_SUCCESS )
return TRUE;
else
{
SetLastErrorEx(result, NULL);
return FALSE;
}
}
BOOL CRegSettings::Read( LPCTSTR szKey, LPCTSTR szName, char& value )
{
HKEY hKey;
if ( GetHKEY( szKey, &hKey, TRUE ) == FALSE )
return FALSE;
ULONG size = sizeof(char);
LONG result =
RegQueryValueEx( hKey, szName, 0, NULL, (LPBYTE)&value, &size );
CloseHKEY( hKey );
if ( result == ERROR_SUCCESS )
return TRUE;
else
{
SetLastErrorEx(result, NULL);
return FALSE;
}
}
BOOL CRegSettings::Read( LPCTSTR szKey, LPCTSTR szName, USHORT& value )
{
HKEY hKey;
if ( GetHKEY( szKey, &hKey, TRUE ) == FALSE )
return FALSE;
ULONG size = sizeof(USHORT);
LONG result =
RegQueryValueEx( hKey, szName, 0, NULL, (LPBYTE)&value, &size );
CloseHKEY( hKey );
if ( result == ERROR_SUCCESS )
return TRUE;
else
{
SetLastErrorEx(result, NULL);
return FALSE;
}
}
BOOL CRegSettings::Read( LPCTSTR szKey, LPCTSTR szName, short& value )
{
HKEY hKey;
if ( GetHKEY( szKey, &hKey, TRUE ) == FALSE )
return FALSE;
ULONG size = sizeof(short);
LONG result =
RegQueryValueEx( hKey, szName, 0, NULL, (LPBYTE)&value, &size );
CloseHKEY( hKey );
if ( result == ERROR_SUCCESS )
return TRUE;
else
{
SetLastErrorEx(result, NULL);
return FALSE;
}
}
BOOL CRegSettings::Read( LPCTSTR szKey, LPCTSTR szName, UINT& value )
{
HKEY hKey;
if ( GetHKEY( szKey, &hKey, TRUE ) == FALSE )
return FALSE;
ULONG size = sizeof(UINT);
LONG result =
RegQueryValueEx( hKey, szName, 0, NULL, (LPBYTE)&value, &size );
CloseHKEY( hKey );
if ( result == ERROR_SUCCESS )
return TRUE;
else
{
SetLastErrorEx(result, NULL);
return FALSE;
}
}
BOOL CRegSettings::Read( LPCTSTR szKey, LPCTSTR szName, int& value )
{
HKEY hKey;
if ( GetHKEY( szKey, &hKey, TRUE ) == FALSE )
return FALSE;
ULONG size = sizeof(int);
LONG result =
RegQueryValueEx( hKey, szName, 0, NULL, (LPBYTE)&value, &size );
CloseHKEY( hKey );
if ( result == ERROR_SUCCESS )
return TRUE;
else
{
SetLastErrorEx(result, NULL);
return FALSE;
}
}
BOOL CRegSettings::Read( LPCTSTR szKey, LPCTSTR szName, ULONG& value )
{
HKEY hKey;
if ( GetHKEY( szKey, &hKey, TRUE ) == FALSE )
return FALSE;
ULONG size = sizeof(ULONG);
LONG result =
RegQueryValueEx( hKey, szName, 0, NULL, (LPBYTE)&value, &size );
CloseHKEY( hKey );
if ( result == ERROR_SUCCESS )
return TRUE;
else
{
SetLastErrorEx(result, NULL);
return FALSE;
}
}
BOOL CRegSettings::Read( LPCTSTR szKey, LPCTSTR szName, long& value )
{
HKEY hKey;
if ( GetHKEY( szKey, &hKey, TRUE ) == FALSE )
return FALSE;
ULONG size = sizeof(long);
LONG result =
RegQueryValueEx( hKey, szName, 0, NULL, (LPBYTE)&value, &size );
CloseHKEY( hKey );
if ( result == ERROR_SUCCESS )
return TRUE;
else
{
SetLastErrorEx(result, NULL);
return FALSE;
}
}
BOOL CRegSettings::Read( LPCTSTR szKey, LPCTSTR szName, float& value )
{
HKEY hKey;
if ( GetHKEY( szKey, &hKey, TRUE ) == FALSE )
return FALSE;
ULONG size = sizeof(float);
LONG result =
RegQueryValueEx( hKey, szName, 0, NULL, (LPBYTE)&value, &size );
CloseHKEY( hKey );
if ( result == ERROR_SUCCESS )
return TRUE;
else
{
SetLastErrorEx(result, NULL);
return FALSE;
}
}
BOOL CRegSettings::Read( LPCTSTR szKey, LPCTSTR szName, double& value )
{
HKEY hKey;
if ( GetHKEY( szKey, &hKey, TRUE ) == FALSE )
return FALSE;
ULONG size = sizeof(double);
LONG result =
RegQueryValueEx( hKey, szName, 0, NULL, (LPBYTE)&value, &size );
CloseHKEY( hKey );
if ( result == ERROR_SUCCESS )
return TRUE;
else
{
SetLastErrorEx(result, NULL);
return FALSE;
}
}
/*
Same thing from above applies here, we deffinitely need to know
the size of receiving bugger. Buffer. Whatever.
*/
BOOL CRegSettings::Read( LPCTSTR szKey, LPCTSTR szName, LPVOID value, ULONG& size )
{
HKEY hKey;
if ( GetHKEY( szKey, &hKey, TRUE ) == FALSE )
return FALSE;
LONG result =
RegQueryValueEx( hKey, szName, 0, NULL, (LPBYTE)value, &size );
CloseHKEY( hKey );
if ( result == ERROR_SUCCESS )
return TRUE;
else
{
SetLastErrorEx(result, NULL);
return FALSE;
}
}
/*
Unlike other Read functions, our dear programmer needs to specify the size
of bugger. I mean, buffer. Check out RegQueryValueEx in MSDN or
Platform SDK if you need to know more.
*/
BOOL CRegSettings::Read( LPCTSTR szKey, LPCTSTR szName, LPTSTR value, ULONG& size )
{
HKEY hKey;
if ( GetHKEY( szKey, &hKey, TRUE ) == FALSE )
return FALSE;
LONG result =
RegQueryValueEx( hKey, szName, 0, NULL, (LPBYTE)value, &size );
CloseHKEY( hKey );
if ( result == ERROR_SUCCESS )
return TRUE;
else
{
SetLastErrorEx(result, NULL);
return FALSE;
}
}