Classe de gestion du registre qui inclut les fonctions principales et d'autres un peu plus perfectionnées. Marche avec l'API Win32, se présente sous un unique fichier d'en-tête.
Deux modes de fonctionnement :
- réel : agit directement sur le registre
- virtuel : enregistre les modifications dans des structures réservées à cet effet (et y charge les données du registre si besoin est) et de cette façon on peut ainsi ultérieurement annuler ou appliquer les modifications, sur une clef, une variable ou toutes les mofications.
Toutes les autres explications nécessaires se trouvent en commentaire dans le fichier lui-même.
Avec la classe est fourni un exemple d'utilisation (main.cpp) qui explique de façon très claire son fonctionnement.
Source / Exemple :
///////////////////////////////////////////////////////////////////////////////////////
// //
//->> CLASSES DE GESTION DU REGISTRE (VALEURS DWORD ET STRING PRISES EN CHARGE) <<-//
// //
///////////////////////////////////////////////////////////////////////////////////////
#include <windows.h>
#include <typeinfo>
#include <stdlib.h>
/* ------------------------------------------------------------------------------------
Name: Log (Classe)
Author: "Heliopraetor"
Description: Avec cette classe, pourrez effectuer toutes les opérations basiques
d'accès au registre.
Date (Commencée): 18/11/03
Date (Terminée (1.0)): 01/02/04
Copyright: ($Author)
Version : 1.0 (Release)
OS: Windows 95/98/Me/XP/NT4/2000
Compilateur: DevC++ | VC++
------------------------------------------------------------------------------------ */
#ifndef __CLASS_REG_MANAGER__
#define __CLASS_REG_MANAGER__
//Déclarations et définitions
class CRegManager; //déclarat° pr RegFolder
template<class TYPE> TYPE rRegGetValue(CRegManager *Ptr, bool open=true); //et RegObject
#define RO_NB true //variables définies pour
#define RO_STR false //le flag RegObject::z_Type
//STRUCTURE UTILISEE POUR OBTENIR LE CONTENU D'UNE CLE par RegEnumValues
struct SDataValues
{
char m_ValueName[256]; //nom de la donnée
char m_ValueContent[256]; //contenu
DWORD m_Type; //type
};
typedef SDataValues* LPSDataValues;
//STRUCTURE DE VARIABLE DU REGISTRE VIRTUELLE
//élément basique, juste une fonction de comparaison
//variables membres commencent par "z_"
template<class PTYPE> struct RegObject
{
//variables
char* z_Name; //nom de la variable
PTYPE z_Obj; //objet-valeur (prévu pour être de type int* ou char*)
bool z_Type; //flag : si z_Obj est un nombre, true (cf RO_NB et RO_STR)
//méthodes
RegObject() : z_Name(NULL), z_Obj(NULL), z_Type(true)
{}
~RegObject()
{
delete z_Name;
delete z_Obj;
}
bool operator ==(char* _str)
{
if (!strcmp(z_Name,_str))
return true;
return false;
}
};
//STRUCTURE D'UNE CLEF DE REGISTRE VIRTUELLE
//prend en charge la gestion des RegObject
//fonctions et variables membres commencent par "z_"
struct RegFolder
{
//variables
HKEY z_HK; //HKEY_CURRENT_USER etc...
char* z_Key; //chemin registre
int z_Nb; //nombre d'éléments
RegObject<void*>** z_Objects; //éléments
//constructeur
RegFolder(HKEY _HK, char* _Key) : z_Key(NULL), z_Nb(0), z_Objects(NULL)
{
z_HK=_HK;
z_Key = new char[strlen(_Key)+1];
strcpy(z_Key, _Key);
}
//destructeur
~RegFolder()
{
delete z_Key;
for (z_Nb--;z_Nb>=0;z_Nb--)
delete z_Objects[z_Nb];
}
//opérateurs d'égalité (pour comparaison facilitée)
bool operator ==(char* _str)
{
if (!strcmp(z_Key,_str))
return true;
return false;
}
bool operator ==(HKEY _HK) {return _HK==z_HK?true:false;}
void zWriteString(char* _name, char* _str)
{
for(int i=0 ; i<z_Nb ; i++)
if (*z_Objects[i]==_name) //si existant
{
delete z_Objects[i]->z_Obj;
z_Objects[i]->z_Obj = static_cast<void*>(new char[strlen(_str)+1]);
strcpy(static_cast<char*>(z_Objects[i]->z_Obj),_str);
z_Objects[i]->z_Type=RO_STR;
return;
}
RegObject<void*>* tmp = new RegObject<void*>; //sinon, nouveau objet
tmp->z_Name = new char[strlen(_name)+1]; //et nouveau
strcpy(tmp->z_Name,_name); //nom
tmp->z_Obj = static_cast<void*>(new char[strlen(_str)+1]); //et nouvelle
strcpy(static_cast<char*>(tmp->z_Obj),_str); //valeur
tmp->z_Type=RO_STR;
RegObject<void*>** tmparr = new RegObject<void*>*[z_Nb+1];
for (i=0 ; i<z_Nb ; i++)
tmparr[i]=z_Objects[i];
tmparr[z_Nb++]=tmp;
delete z_Objects;
z_Objects=tmparr;
}
void zWriteInt(char* _name, int _value)
{
int* t=new int(_value);
for(int i=0 ; i<z_Nb ; i++)
if (*z_Objects[i]==_name) //si existant
{
delete z_Objects[i]->z_Obj;
z_Objects[i]->z_Obj = static_cast<void*>(t);
z_Objects[i]->z_Type=RO_NB;
return;
}
RegObject<void*>* tmp = new RegObject<void*>; //sinon, nouveau objet
tmp->z_Name = new char[strlen(_name)+1]; //et nouveau
strcpy(tmp->z_Name,_name); //nom
tmp->z_Obj = static_cast<void*>(t); //et nouvelle valeur
tmp->z_Type=RO_NB;
RegObject<void*>** tmparr = new RegObject<void*>*[z_Nb+1];
for (i=0 ; i<z_Nb ; i++)
tmparr[i]=z_Objects[i];
tmparr[z_Nb++]=tmp;
delete z_Objects;
z_Objects=tmparr;
}
int zGetInt(char* _name)
{
int result=-1;
for(int i=0 ; i<z_Nb ; i++)
if (*z_Objects[i]==_name)
{
if (z_Objects[i]->z_Type) //pour éviter les erreurs de type
result = *static_cast<int*>(z_Objects[i]->z_Obj);
break;
}
return result;
}
char* zGetString(char* _name)
{
for(int i=0 ; i<z_Nb ; i++)
if (*z_Objects[i]==_name)
{
if (z_Objects[i]->z_Type) //pour éviter les erreurs de type
return NULL;
char* result = new char[strlen(static_cast<char*>(z_Objects[i]->z_Obj))+1];
strcpy(result, static_cast<char*>(z_Objects[i]->z_Obj));
return result;
}
return NULL;
}
void zDeleteValue(char* _name)
{
for(int u=0 ; u<z_Nb ; u++)
if (*z_Objects[u]==_name)
{
delete z_Objects[u];
RegObject<void*>** TmpList = new RegObject<void*>*[z_Nb-1];
if (TmpList==NULL) return;
for (int i=0 ; i<u ; i++)
TmpList[i] = z_Objects[i];
z_Nb--;
for (i=u ; i<z_Nb ; i++)
TmpList[i] = z_Objects[i+1];
delete z_Objects;
z_Objects=TmpList;
break;
}
}
RegObject<void*>* zGetObject(char* _name)
{
for(int u=0 ; u<z_Nb ; u++)
if (*z_Objects[u]==_name)
return z_Objects[u];
return NULL;
}
};
//CLASSE DE GESTION DU REGISTRE
//
//deux modes de fonctionnement : - direct/réel (agit immédiatement sur le registre)
// - indirect/virtuel (agit sur un registre virtuel qui pourra
// être appliqué au vrai registre, ou annulé, ultérieurement)
//Pour le mode direct, les fonctions commencent par la lettre "r" comme "réel".
//Pour le mode indirect, les fonctions commencent par la lettre "v" comme "virtuel".
//Les autres fonctions concernent des commandes marchant pour les deux modes.
//
//Pour les fonctions Get*(), les valeurs retournées en cas d'erreur sont -1 ou NULL, selon le
//type de la valeur de retour. Elles peuvent être causées par des erreurs de type (par exemple,
//rGetInt() appelée pour une clé qui est en fait une chaîne de caractère, renverra -1).
class CRegManager
{
private:
//--registre virtuel
RegFolder** m_VRegister; //registre virtuel
int m_AcF; //dossier actuel
int m_nFolder; //nbre de dossiers chargés
//--variables temporaires--
HKEY m_HK; //HKEY_CURRENT_USER etc....
char* m_Key; //Clef1\Clef2\Clef3\ /
char* m_ValueName; //Nom de la variable registre contenant
HKEY m_tHK; //pour ouvrir
DWORD m_tRes;
//--sécurity attributes
SECURITY_ATTRIBUTES m_SA;
public:
//---------constructeur
CRegManager() : m_VRegister(NULL), m_nFolder(0), m_HK(NULL), m_Key(NULL), m_tHK(NULL),
m_ValueName(NULL), m_AcF(0)
{
m_SA.nLength = sizeof (SECURITY_ATTRIBUTES);
m_SA.lpSecurityDescriptor = NULL;
m_SA.bInheritHandle = TRUE;
}
//---------destructeur
~CRegManager()
{
for (int i=0;i<m_nFolder;i++)
delete m_VRegister[i];
delete m_Key;
delete m_ValueName;
}
//configuration des paramètres
inline void SetHK(HKEY _HK) { m_HK = _HK; }
inline void SetKey(char* _Key)
{
delete m_Key;
m_Key = new char[strlen(_Key)+1];
strcpy(m_Key, _Key);
}
inline void SetValueName(char* _ValueName)
{
delete m_ValueName;
m_ValueName = new char[strlen(_ValueName)+1];
strcpy(m_ValueName, _ValueName);
}
//obtention des paramètres
inline HKEY GetHK() const { return m_HK; }
inline char* GetKey() const { return m_Key; }
inline char* GetValueName() const { return m_ValueName; }
inline int GetValuesCount()
{
int i =-1;
RegOpenKeyEx(m_HK,m_Key,0,KEY_QUERY_VALUE,&m_tHK);
RegQueryInfoKey(m_tHK,NULL,NULL,NULL,NULL,NULL,NULL,(ULONG*)&i,NULL,NULL,NULL,NULL);
return i;
}
inline bool EnumValues(LPSDataValues _Tab)
{
if( !m_HK || !m_Key )
return false;
long l_Res;
int i=0,
l_MaxSize=255;
RegOpenKeyEx(m_HK,m_Key,0,KEY_QUERY_VALUE,&m_tHK);
do
{
l_Res = RegEnumValue(m_tHK,
i,
_Tab[i].m_ValueName,
(unsigned long*)&l_MaxSize,
NULL,
&_Tab[i].m_Type,
(unsigned char*)&_Tab[i].m_ValueContent,
(unsigned long*)&l_MaxSize);
i++;
}
while( l_Res != ERROR_NO_MORE_ITEMS );
return true;
}
//fonction de focalisation sur une clé registre virtuelle (avec création le cas échéant)
void vSetKeyAsActual(bool create=true)
{
//---------------------------réponse rapide-----------------------------------------
if( !m_HK || !m_Key) return; //si l'initialisation n'a eu lieu
if (m_nFolder)
{
if (m_AcF!=-1)
if (*m_VRegister[m_AcF]==m_HK && *m_VRegister[m_AcF]==m_Key)//si l'actuel
return;
for(m_AcF=0 ; m_AcF<m_nFolder ; m_AcF++)
if (*m_VRegister[m_AcF]==m_HK && *m_VRegister[m_AcF]==m_Key)//si existant
return;
}
if (!create) {m_AcF=-1;return;}
//----------------------------création d'un folder virtuel--------------------------
RegFolder* tmp = new RegFolder(m_HK, m_Key); //allocation
RegCreateKeyEx(m_HK,m_Key,0,NULL,REG_OPTION_NON_VOLATILE,
KEY_QUERY_VALUE,&m_SA,&m_tHK,NULL); //on ouvre/crée le vrai folder
//on compte le nb d'éléments du vrai folder
RegQueryInfoKey(m_tHK,NULL,NULL,NULL,NULL,NULL,NULL,(ULONG*)&tmp->z_Nb,NULL,NULL,NULL,NULL);
if (tmp->z_Nb) //s'il en a déjà, on doit les inclure dans le virtual folder
{
tmp->z_Objects = new RegObject<void*>*[tmp->z_Nb]; //on alloue
ULONG tmp_Type,lenght;
char* _ValueNames=m_ValueName;
for(DWORD x=0;x<tmp->z_Nb;x++)
{
tmp->z_Objects[x] = new RegObject<void*>; //on crée une variable virtuelle
lenght=260; m_ValueName=new char[lenght+1];
RegEnumValue(m_tHK,x,m_ValueName,&lenght,0,NULL,NULL,NULL);
delete m_ValueName;
m_ValueName=new char[++lenght];
tmp_Type=0; //on récupère le nom et le type de la vraie variable
RegEnumValue(m_tHK,x,m_ValueName,&lenght,0,&tmp_Type,NULL,NULL);
if ((int)tmp_Type == REG_SZ) //on récupère la variable selon son type
{tmp->z_Objects[x]->z_Obj = static_cast<void*>(rRegGetValue<char*>(this,false));tmp->z_Objects[x]->z_Type=RO_STR;}
else
{tmp->z_Objects[x]->z_Obj = static_cast<void*>(rRegGetValue<int*>(this,false));tmp->z_Objects[x]->z_Type=RO_NB;}
tmp->z_Objects[x]->z_Name=m_ValueName; //on effectue le transfert de nom
m_ValueName=NULL;
}
m_ValueName=_ValueNames;
}
//ajout du folder virtuel créé au registre virtuel
RegCloseKey(m_tHK);
RegFolder** tmparr = new RegFolder*[m_nFolder+1];
for (int i=0 ; i<m_nFolder ; i++)
tmparr[i]=m_VRegister[i];
tmparr[m_nFolder++]=tmp;
delete m_VRegister;
m_VRegister=tmparr;
}
//écritures dans le registre virtuel
bool vWriteString(char* _Str)
{
if( !m_HK || !m_Key || !m_ValueName || !_Str )
return false; //si l'initialisation n'a eu lieu
vSetKeyAsActual();
m_VRegister[m_AcF]->zWriteString(m_ValueName,_Str);
return true; //ok
}
bool vWriteInt(int _Value)
{
if( !m_HK || !m_Key || !m_ValueName || !_Value )
return false; //si l'initialisation n'a eu lieu
vSetKeyAsActual();
m_VRegister[m_AcF]->zWriteInt(m_ValueName,_Value);
return true; //ok
}
//lectures dans le registre virtuel
int vGetInt()
{
if( !m_HK || !m_Key || !m_ValueName)
return NULL; //si l'initialisation n'a eu lieu
vSetKeyAsActual();
return m_VRegister[m_AcF]->zGetInt(m_ValueName); //ok
}
char* vGetString()
{
if( !m_HK || !m_Key || !m_ValueName)
return NULL; //si l'initialisation n'a eu lieu
vSetKeyAsActual();
return m_VRegister[m_AcF]->zGetString(m_ValueName);
}
//lectures dans le VRAI registre
int rGetInt(bool open=true)
{
if( !m_HK || !m_Key || !m_ValueName) return -1; //si pas d'initialisation
if (open) RegOpenKeyEx(m_HK, m_Key,0,KEY_QUERY_VALUE,&m_tHK);
long *Nb = NULL; Nb = new long;
unsigned long SizeOfInt = 4, Type;
RegQueryValueEx(m_tHK,m_ValueName,0,&Type,(unsigned char*)Nb,&SizeOfInt);
if (open) RegCloseKey(m_tHK);
if( Nb == NULL || Type!=REG_DWORD ) //erreur de type
{
delete Nb;
return -1;
}
int result = (*Nb);
delete Nb;
return result;
}
char* rGetString(bool open=true) // !!!!!! renvoie une chaîne "LIBRE"-> à l'utilisateur de la supprimer
{
if( !m_HK || !m_Key || !m_ValueName) return NULL; //si l'initialisation n'a eu lieu
if (open) RegOpenKeyEx(m_HK, m_Key,0,KEY_QUERY_VALUE, &m_tHK);
//recupere la taille de la clé pour connaitre la taille du buffer à spécifier
unsigned long lenght=0, Type;
RegQueryValueEx(m_tHK, m_ValueName, NULL, &Type, NULL, &lenght);
if ( Type!=REG_SZ ) //erreur de type
{
if (open) RegCloseKey(m_tHK);
return NULL;
}
char* _TmpStr = new char[lenght];
if( RegQueryValueEx(m_tHK,m_ValueName,NULL,NULL,(unsigned char*)_TmpStr,&lenght) )
{
delete [] _TmpStr;
return NULL;
}
if (open) RegCloseKey(m_tHK);
return _TmpStr; //ok
}
//écritures internes dans le VRAI registre
bool rWriteInt(int _Value)
{
if( !m_HK || !m_Key || !m_ValueName )
return false; //si l'initialisation n'a eu lieu
RegCreateKeyEx(m_HK,m_Key,0,"",REG_OPTION_NON_VOLATILE,KEY_WRITE,&m_SA,&m_tHK,&m_tRes);
RegSetValueEx(m_tHK, m_ValueName, 0, REG_DWORD, (unsigned char*)&_Value,sizeof(int));
RegCloseKey(m_tHK);
return true; //ok
}
bool rWriteString(char *_String)
{
if( !m_HK || !m_Key || !m_ValueName || !_String )
return false; //si l'initialisation n'a eu lieu
RegCreateKeyEx(m_HK,m_Key,0,"", REG_OPTION_NON_VOLATILE, KEY_WRITE, &m_SA, &m_tHK, &m_tRes);
RegSetValueEx( m_tHK, m_ValueName,0, REG_SZ , (unsigned char*)_String, strlen(_String)+1);
RegCloseKey(m_tHK);
return true; //ok
}
//suppressions (réelles ET virtuelles)
bool DeleteKey()
{
if( !m_HK || !m_Key ) return false;
if( RegDeleteKey(m_HK,m_Key) != ERROR_SUCCESS ) //suppression réelle
return false;
vAbortKey(); //puis virtuelle
return true;
}
bool DeleteValue()
{
if( !m_HK || !m_Key || !m_ValueName)
return false;
RegOpenKeyEx(m_HK,m_Key,0,KEY_WRITE,&m_tHK); //suppression
if( RegDeleteValue(m_tHK,m_ValueName) != ERROR_SUCCESS )//réelle
return false;
RegCloseKey(m_tHK);
vAbortValue(); //puis virtuelle
return true;
}
//annulations
void vAbortAll()
{
for (int i=0;i<m_nFolder;i++)
delete m_VRegister[i];
m_nFolder=0; m_AcF=0;
}
void vAbortKey()
{
vSetKeyAsActual(false);
if (m_AcF==-1) return;
delete m_VRegister[m_AcF]; //------------suppression virtuelle
RegFolder** TmpList = new RegFolder*[m_nFolder-1];
for (int i=0 ; i<m_AcF ; i++)
TmpList[i] = m_VRegister[i];
m_nFolder--;
for (i=m_AcF ; i<m_nFolder ; i++)
TmpList[i] = m_VRegister[i+1];
delete m_VRegister;
m_VRegister=TmpList;
}
void vAbortValue()
{
if (!m_ValueName) return;
vSetKeyAsActual(false);
if (m_AcF==-1) return;
m_VRegister[m_AcF]->zDeleteValue(m_ValueName); //puis suppression virtuelle
}
//validations
void vApplyAll()
{
for (m_AcF=0;m_AcF<m_nFolder;m_AcF++)
{
int tmp = m_VRegister[m_AcF]->z_Nb;
RegCreateKeyEx(m_VRegister[m_AcF]->z_HK,m_VRegister[m_AcF]->z_Key,0,"", REG_OPTION_NON_VOLATILE, KEY_WRITE, &m_SA, &m_tHK, &m_tRes);
for (int i=0 ; i<tmp ; i++) //boucle
{
RegObject<void*>* tmp_obj = m_VRegister[m_AcF]->z_Objects[i];
if (tmp_obj->z_Type)
RegSetValueEx(m_tHK,tmp_obj->z_Name,0,REG_DWORD,(unsigned char*)tmp_obj->z_Obj,sizeof(int));
else
RegSetValueEx(m_tHK,tmp_obj->z_Name,0,REG_SZ,(unsigned char*)tmp_obj->z_Obj,strlen((char*)tmp_obj->z_Obj)+1);
}
RegCloseKey(m_tHK);
}
vAbortAll();
}
void vApplyKey()
{
if( !m_HK || !m_Key || !m_ValueName ) return; //si l'initialisation n'a eu lieu
vSetKeyAsActual(false);
if (m_AcF==-1) return;
int tmp = m_VRegister[m_AcF]->z_Nb;
RegCreateKeyEx(m_HK,m_Key,0,"", REG_OPTION_NON_VOLATILE, KEY_WRITE, &m_SA, &m_tHK, &m_tRes);
for (int i=0 ; i<tmp ; i++) //boucle
{
RegObject<void*>* tmp_obj = m_VRegister[m_AcF]->z_Objects[i];
if (tmp_obj->z_Type)
RegSetValueEx(m_tHK,m_ValueName,0,REG_DWORD,(unsigned char*)tmp_obj->z_Obj,sizeof(int));
else
RegSetValueEx(m_tHK,m_ValueName,0,REG_SZ,(unsigned char*)tmp_obj->z_Obj,strlen((char*)tmp_obj->z_Obj)+1);
}
RegCloseKey(m_tHK);
vAbortKey();
}
void vApplyValue()
{
if( !m_HK || !m_Key || !m_ValueName ) return; //si l'initialisation n'a eu lieu
vSetKeyAsActual(false);
if (m_AcF==-1) return;
RegObject<void*>* tmp = m_VRegister[m_AcF]->zGetObject(m_ValueName);
RegCreateKeyEx(m_HK,m_Key,0,"", REG_OPTION_NON_VOLATILE, KEY_WRITE, &m_SA, &m_tHK, &m_tRes);
if (tmp->z_Type)
RegSetValueEx(m_tHK,m_ValueName,0,REG_DWORD,(unsigned char*)tmp->z_Obj,sizeof(int));
else
RegSetValueEx(m_tHK,m_ValueName,0,REG_SZ,(unsigned char*)tmp->z_Obj,strlen((char*)tmp->z_Obj)+1);
RegCloseKey(m_tHK);
m_VRegister[m_AcF]->zDeleteValue(m_ValueName); //suppression virtuelle
}
};
//lecture générale dans le registre virtuel
//en fonction du type voulu
template<class TYPE> TYPE vRegGetValue(CRegManager *Ptr)
{
const char* Type = typeid(TYPE).name();
if( !strcmp(Type,"char *") ) //char* ?
return (TYPE)Ptr->vGetString();
else if( !strcmp(Type,"char") ) //char ?
return (TYPE)&(Ptr->vGetString())[0];
else if( !strcmp(Type,"int") ) //int ?
return (TYPE)Ptr->vGetInt();
else if( !strcmp(Type,"int *") ) //int* ?
{
int* a = new int;
return (TYPE)a;
}
else
return NULL; //type autre ou inconnu
}
//lecture générale dans le VRAI registre
//en fonction du type désiré
template<class TYPE> TYPE rRegGetValue(CRegManager *Ptr, bool open)
{
const char* Type = typeid(TYPE).name();
if( !strcmp(Type,"char *") ) //char* ?
return (TYPE)Ptr->rGetString(open);
else if( !strcmp(Type,"char") ) //char ?
return (TYPE)&(Ptr->rGetString(open))[0];
else if( !strcmp(Type,"int") ) //int ?
return (TYPE)Ptr->rGetInt(open);
else if( !strcmp(Type,"int *") ) //int* ?
{
int* a = new int;
return (TYPE)a;
}
else
return NULL; //type autre ou inconnu
}
#endif
Conclusion :
Ayant voulu nous concentrer sur le registre et l'api windows, nous avons consciemment évité l'emploi d'autres librairies et de leurs classes.
Ce code est utilisé en partie dans un autre soft, waterball. Il est ici mis à part pour l'expliquer dans une version mieux anotée et ainsi pour mieux le mettre en valeur.
Vous n'êtes pas encore membre ?
inscrivez-vous, c'est gratuit et ça prend moins d'une minute !
Les membres obtiennent plus de réponses que les utilisateurs anonymes.
Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.
Le fait d'être membre vous permet d'avoir des options supplémentaires.