分享

c++中注册表操作

 weicat 2009-12-10

 c++中注册表操作 收藏
    在前一篇中,我有提到应用程序关联的方法,归根结底就是在注册表中添加了相应的内容。但这样有个不好的地方,就是会在注册表中留下很多垃圾信息。怎样在调试完程序后,自动清除注册表中冗余的信息呢?我在这里提供一个简单的方法,与大家分享哈。

    (一)跟大家介绍一个c++的注册表操作的封装类

1.注册表项RegEntry.h

view plaincopy to clipboardprint?
// CRegEntry: interface for the CRegEntry class.  
//  
//////////////////////////////////////////////////////////////////////  
 
#if !defined(_REGENTRY_H_INCLUDED)  
#define _REGENTRY_H_INCLUDED  
 
#if _MSC_VER > 1000  
#pragma once  
#endif // _MSC_VER > 1000  
 
class CRegistry;  
 
class CRegEntry  
{  
public:  
 
    CRegEntry(CRegistry* Owner = NULL);       
    virtual ~CRegEntry() { if (lpszName) delete [] lpszName; if (lpszStr) delete [] lpszStr; };  
 
    /* -----------------------------------------* 
     *  Operators                               * 
     * -----------------------------------------*/ 
      
    CRegEntry&  operator =( CRegEntry& cregValue );  
    CRegEntry&  operator =( LPCTSTR lpszValue );  
    CRegEntry&  operator =( LPDWORD lpdwValue );      
    CRegEntry&  operator =( DWORD dwValue ) { return (*this = &dwValue); }    
                operator LPTSTR();  
                operator DWORD();  
 
      
    // Data types without implemented conversions  
    // NOTE: I realize these will only check asserts  
    // when a value is set and retrieved during the  
    // same session. But it is better than no check.  
 
    REGENTRY_NONCONV_STORAGETYPE(POINT);  
    REGENTRY_NONCONV_STORAGETYPE(RECT);  
 
    // Numeric types with conversions  
    // If you'd like to add more, follow this form:  
    // data type, max string length + 1, format specification, from string, from DWORD  
 
    REGENTRY_CONV_NUMERIC_STORAGETYPE(__int64, 28, %I64d, _ttoi64(lpszStr), (__int64)dwDWORD)  
    REGENTRY_CONV_NUMERIC_STORAGETYPE(double, 18, %f, _tcstod(lpszStr, NULL), (double)dwDWORD)    
    REGENTRY_CONV_NUMERIC_STORAGETYPE(bool, 2, %d, (_ttoi(lpszStr) != 0), (dwDWORD != 0))  
    REGENTRY_CONV_NUMERIC_STORAGETYPE(int, 12, %d, _ttoi(lpszStr), (int)dwDWORD)  
    REGENTRY_CONV_NUMERIC_STORAGETYPE(UINT, 11, %d, (UINT)_tcstoul(lpszStr, NULL, NULL), (UINT)dwDWORD)  
 
    // Types with conversions: type to/from string, type from unsigned long  
 
    REGENTRY_CONV_STORAGETYPE(tstring, _R_BUF(_MAX_REG_VALUE); _tcscpy(buffer, Value.c_str());,  
    lpszStr, _ultot(dwDWORD, lpszStr, NULL), _T(""))  
          
 
    /* -----------------------------------------* 
     *  Member Variables and Functions          * 
     * -----------------------------------------*/ 
      
    LPTSTR      lpszName;   // The value name  
    UINT        iType;      // Value data type  
      
    void        InitData(CRegistry* Owner = NULL);    
    void        ForceStr();  
    bool        Delete();     
 
 
    /* The following six functions handle REG_MULTI_SZ support: */ 
 
    void        SetMulti(LPCTSTR lpszValue, size_t nLen, bool bInternal = false);     
    void        MultiRemoveAt(size_t nIndex);  
    void        MultiSetAt(size_t nIndex, LPCTSTR lpszVal);  
    LPTSTR      GetMulti(LPTSTR lpszDest, size_t nMax = _MAX_REG_VALUE);  
    LPCTSTR     MultiGetAt(size_t nIndex);    
    size_t      MultiLength(bool bInternal = false);  
    size_t      MultiCount();  
          
 
    void        SetBinary(LPBYTE lpbValue, size_t nLen);      
    void        GetBinary(LPBYTE lpbDest, size_t nMaxLen);  
    size_t      GetBinaryLength();  
    bool        Convertible() { return __bConvertable; }  
 
    __inline    SetOwner(CRegistry* Owner) { __cregOwner = Owner; }  
      
    template <class T>void SetStruct(T &type) { SetBinary((LPBYTE) &type, sizeof(T)); }  
    template <class T>void GetStruct(T &type) { GetBinary((LPBYTE) &type, sizeof(T)); }  
      
    __inline    IsString()      { return (iType == REG_SZ); }  
    __inline    IsDWORD()       { return (iType == REG_DWORD); }  
    __inline    IsBinary()      { return (iType == REG_BINARY); }     
    __inline    IsMultiString() { return (iType == REG_MULTI_SZ); }  
      
    __inline    IsStored()      { return __bStored; }  
    __inline    Exists()        { return __bStored; }  
 
    __inline    MultiClear()    { SetMulti(_T("\0"), 2); }  
    __inline    MultiAdd(LPCTSTR lpszVal) { MultiSetAt(MultiCount(), lpszVal); }  
 
protected:  
 
    CRegistry*  __cregOwner;  
    bool        __bConvertable;  
    bool        __bStored;  
 
private:  
 
    /* Create a variable for each prominent data type */ 
 
    DWORD       dwDWORD;      
    LPTSTR      lpszStr;  
          
    std::vector<BYTE> vBytes;  
    std::vector<tstring> vMultiString;  
};  
 
 
#endif 
// CRegEntry: interface for the CRegEntry class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(_REGENTRY_H_INCLUDED)
#define _REGENTRY_H_INCLUDED

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

class CRegistry;

class CRegEntry
{
public:

 CRegEntry(CRegistry* Owner = NULL);  
 virtual ~CRegEntry() { if (lpszName) delete [] lpszName; if (lpszStr) delete [] lpszStr; };

 /* -----------------------------------------*
  * Operators        *
  * -----------------------------------------*/
 
 CRegEntry& operator =( CRegEntry& cregValue );
 CRegEntry& operator =( LPCTSTR lpszValue );
 CRegEntry& operator =( LPDWORD lpdwValue ); 
 CRegEntry& operator =( DWORD dwValue ) { return (*this = &dwValue); } 
    operator LPTSTR();
    operator DWORD();

 
 // Data types without implemented conversions
 // NOTE: I realize these will only check asserts
 // when a value is set and retrieved during the
 // same session. But it is better than no check.

 REGENTRY_NONCONV_STORAGETYPE(POINT);
 REGENTRY_NONCONV_STORAGETYPE(RECT);

 // Numeric types with conversions
 // If you'd like to add more, follow this form:
 // data type, max string length + 1, format specification, from string, from DWORD

 REGENTRY_CONV_NUMERIC_STORAGETYPE(__int64, 28, %I64d, _ttoi64(lpszStr), (__int64)dwDWORD)
 REGENTRY_CONV_NUMERIC_STORAGETYPE(double, 18, %f, _tcstod(lpszStr, NULL), (double)dwDWORD) 
 REGENTRY_CONV_NUMERIC_STORAGETYPE(bool, 2, %d, (_ttoi(lpszStr) != 0), (dwDWORD != 0))
 REGENTRY_CONV_NUMERIC_STORAGETYPE(int, 12, %d, _ttoi(lpszStr), (int)dwDWORD)
 REGENTRY_CONV_NUMERIC_STORAGETYPE(UINT, 11, %d, (UINT)_tcstoul(lpszStr, NULL, NULL), (UINT)dwDWORD)

 // Types with conversions: type to/from string, type from unsigned long

 REGENTRY_CONV_STORAGETYPE(tstring, _R_BUF(_MAX_REG_VALUE); _tcscpy(buffer, Value.c_str());,
 lpszStr, _ultot(dwDWORD, lpszStr, NULL), _T(""))
  

 /* -----------------------------------------*
  * Member Variables and Functions   *
  * -----------------------------------------*/
 
 LPTSTR  lpszName; // The value name
 UINT  iType;  // Value data type
 
 void  InitData(CRegistry* Owner = NULL); 
 void  ForceStr();
 bool  Delete(); 


 /* The following six functions handle REG_MULTI_SZ support: */

 void  SetMulti(LPCTSTR lpszValue, size_t nLen, bool bInternal = false); 
 void  MultiRemoveAt(size_t nIndex);
 void  MultiSetAt(size_t nIndex, LPCTSTR lpszVal);
 LPTSTR  GetMulti(LPTSTR lpszDest, size_t nMax = _MAX_REG_VALUE);
 LPCTSTR  MultiGetAt(size_t nIndex); 
 size_t  MultiLength(bool bInternal = false);
 size_t  MultiCount();
  

 void  SetBinary(LPBYTE lpbValue, size_t nLen); 
 void  GetBinary(LPBYTE lpbDest, size_t nMaxLen);
 size_t  GetBinaryLength();
 bool  Convertible() { return __bConvertable; }

 __inline SetOwner(CRegistry* Owner) { __cregOwner = Owner; }
 
 template <class T>void SetStruct(T &type) { SetBinary((LPBYTE) &type, sizeof(T)); }
 template <class T>void GetStruct(T &type) { GetBinary((LPBYTE) &type, sizeof(T)); }
 
 __inline IsString()  { return (iType == REG_SZ); }
 __inline IsDWORD()  { return (iType == REG_DWORD); }
 __inline IsBinary()  { return (iType == REG_BINARY); } 
 __inline IsMultiString() { return (iType == REG_MULTI_SZ); }
 
 __inline IsStored()  { return __bStored; }
 __inline Exists()  { return __bStored; }

 __inline MultiClear() { SetMulti(_T("\0"), 2); }
 __inline MultiAdd(LPCTSTR lpszVal) { MultiSetAt(MultiCount(), lpszVal); }

protected:

 CRegistry* __cregOwner;
 bool  __bConvertable;
 bool  __bStored;

private:

 /* Create a variable for each prominent data type */

 DWORD  dwDWORD; 
 LPTSTR  lpszStr;
  
 std::vector<BYTE> vBytes;
 std::vector<tstring> vMultiString;
};


#endif

2.注册表节点Registry.h

view plaincopy to clipboardprint?
#if !defined(_REGISTRY_H_INCLUDED)  
#define _REGISTRY_H_INCLUDED  
 
#if _MSC_VER > 1000  
#pragma once  
#endif // _MSC_VER > 1000  
 
/* Silence STL warnings */ 
 
#pragma warning (disable : 4786)  
#pragma warning (disable : 4514)  
#pragma warning (push, 3)  
 
#ifdef _UNICODE  
#if !defined(UNICODE)  
#define UNICODE   
#endif  
#endif  
 
#include <windows.h>  
#include <math.h>  
#include <TCHAR.h>  
#include <stdlib.h>  
#include <stdio.h>  
#include <vector>  
#include <assert.h>  
 
 
/* ==================================== 
 * Begin Preprocessor Definitions 
 * 
 * - Ugly, but well worth it. 
 * ==================================== */ 
 
 
#ifdef _UNICODE  
typedef std::wstring tstring;  
#else  
typedef std::string tstring;  
#endif  
 
 
/* CRegistry Open Flags */ 
 
#define CREG_CREATE     1  
#define CREG_AUTOOPEN   2  
#define CREG_NOCACHE    4  
 
/* CRegistry Behaivor flags */ 
 
#define CREG_LOADING    8  
 
 
#define _MAX_REG_VALUE  2048    // Maximum Value length, this may be increased  
 
#define NOT_ES(func)            func != ERROR_SUCCESS  
#define IS_ES(func)             func == ERROR_SUCCESS  
#define _R_BUF(size)            _TCHAR buffer[size]  
 
#define REGENTRY_AUTO           __cregOwner->GetFlags() & CREG_AUTOOPEN  
#define REGENTRY_TRYCLOSE       if (REGENTRY_AUTO) __cregOwner->AutoClose()  
#define REGENTRY_SZ_SAFE        iType == REG_SZ || iType == REG_BINARY  
#define REGENTRY_ALLOWCONV(b)   __bConvertable = b;  
 
 
#define REGENTRY_REFRESH_IF_NOCACHE \  
    if (__cregOwner->GetFlags() & CREG_NOCACHE && \  
        REGENTRY_NOTLOADING && REGENTRY_KEYVALID( KEY_QUERY_VALUE ))\  
        __cregOwner->Refresh();  
 
#define REGENTRY_UPDATE_MULTISTRING \  
    LPTSTR lpszBuffer = new _TCHAR[_MAX_REG_VALUE]; \  
    REGENTRY_SETLOADING(+); GetMulti(lpszBuffer); REGENTRY_SETLOADING(-); \  
    SetMulti(lpszBuffer, MultiLength(true), true); \  
    delete [] lpszBuffer;  
 
      
#define REGENTRY_KEYVALID(auto_access) \  
    lpszName && ((REGENTRY_AUTO && __cregOwner->AutoOpen(auto_access)) || (!(REGENTRY_AUTO) && __cregOwner->hKey != NULL))  
 
#define REGENTRY_NOTLOADING \  
    !(__cregOwner->GetFlags() & CREG_LOADING)  
 
#define REGENTRY_SETLOADING(op) \  
    __cregOwner->__dwFlags op= CREG_LOADING  
 
#define REGENTRY_BINARYTOSTRING \  
    if (iType == REG_BINARY) { ForceStr(); lpszStr = *this; }   
 
#define REGENTRY_NONCONV_STORAGETYPE(type) \  
    CRegEntry& operator=( type &Value ){ REGENTRY_ALLOWCONV(false) SetStruct(Value); return *this; }  \  
    operator type(){ type Return; GetStruct(Return); return Return; }  
 
#define REGENTRY_CONV_STORAGETYPE(type, to_sz, from_sz, from_dw, no_result) \  
    CRegEntry& operator=( type Value ) { to_sz return (*this = (LPCTSTR)(buffer)); } \  
    operator type(){ REGENTRY_BINARYTOSTRING return (REGENTRY_SZ_SAFE ? from_sz :(iType == REG_DWORD ? from_dw : no_result)); }  
 
#define REGENTRY_CONV_NUMERIC_STORAGETYPE(type, maxlen, form, from_sz, from_dw) \  
    REGENTRY_CONV_STORAGETYPE(type, _R_BUF(maxlen); _stprintf(buffer, _T(#form), Value);, from_sz, from_dw, 0)  
 
 
/* ==================================== 
 * Include CRegEntry Class Definition 
 * ==================================== */ 
 
#include "RegEntry.h"  
 
/* ==================================== 
 * Begin CRegistry Class Definition 
 * ==================================== */ 
 
using namespace std;  
 
class CRegistry {  
 
public:  
      
    CRegistry   (DWORD flags = CREG_CREATE);      
    virtual     ~CRegistry() { Close(); for (int i=0; i < _reEntries.size(); ++i) delete _reEntries[i]; delete [] _lpszSubKey; }  
 
    CRegEntry&  operator[](LPCTSTR lpszVName);  
    CRegEntry*  GetAt(size_t n) { assert(n < Count());  return _reEntries.at(n); }  
      
    bool        Open(LPCTSTR lpszRegPath, HKEY hRootKey = HKEY_LOCAL_MACHINE,  
                DWORD dwAccess = KEY_QUERY_VALUE | KEY_SET_VALUE, bool bAuto = false);  
      
    bool        AutoOpen(DWORD dwAccess);  
    void        AutoClose();  
    void        Close();  
    bool        Refresh();    
 
    static bool KeyExists(LPCTSTR lpszRegPath, HKEY hRootKey = HKEY_LOCAL_MACHINE);  
    bool        SubKeyExists(LPCTSTR lpszSub);    
      
    void        DeleteKey();      
 
    __inline    GetFlags()  {   return __dwFlags; }  
    __inline    Count()     {   return _reEntries.size(); }  
      
    HKEY        hKey;       /* Registry key handle */ 
 
protected:  
      
    DWORD       __dwFlags;  
    friend      void CRegEntry::MultiSetAt(size_t nIndex, LPCTSTR lpszVal);  
    friend      void CRegEntry::MultiRemoveAt(size_t nIndex);  
 
private:  
 
    void        InitData();   
    void        DeleteKey(HKEY hPrimaryKey, LPCTSTR lpszSubKey);  
 
    HKEY        _hRootKey;  
    LPTSTR      _lpszSubKey;  
 
    std::vector<CRegEntry *> _reEntries;  
};  
 
#pragma warning(pop)  
 
#endif 
#if !defined(_REGISTRY_H_INCLUDED)
#define _REGISTRY_H_INCLUDED

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

/* Silence STL warnings */

#pragma warning (disable : 4786)
#pragma warning (disable : 4514)
#pragma warning (push, 3)

#ifdef _UNICODE
#if !defined(UNICODE)
#define UNICODE
#endif
#endif

#include <windows.h>
#include <math.h>
#include <TCHAR.h>
#include <stdlib.h>
#include <stdio.h>
#include <vector>
#include <assert.h>


/* ====================================
 * Begin Preprocessor Definitions
 *
 * - Ugly, but well worth it.
 * ==================================== */


#ifdef _UNICODE
typedef std::wstring tstring;
#else
typedef std::string tstring;
#endif


/* CRegistry Open Flags */

#define CREG_CREATE  1
#define CREG_AUTOOPEN 2
#define CREG_NOCACHE 4

/* CRegistry Behaivor flags */

#define CREG_LOADING 8


#define _MAX_REG_VALUE 2048 // Maximum Value length, this may be increased

#define NOT_ES(func)   func != ERROR_SUCCESS
#define IS_ES(func)    func == ERROR_SUCCESS
#define _R_BUF(size)   _TCHAR buffer[size]

#define REGENTRY_AUTO   __cregOwner->GetFlags() & CREG_AUTOOPEN
#define REGENTRY_TRYCLOSE  if (REGENTRY_AUTO) __cregOwner->AutoClose()
#define REGENTRY_SZ_SAFE  iType == REG_SZ || iType == REG_BINARY
#define REGENTRY_ALLOWCONV(b) __bConvertable = b;


#define REGENTRY_REFRESH_IF_NOCACHE \
 if (__cregOwner->GetFlags() & CREG_NOCACHE && \
  REGENTRY_NOTLOADING && REGENTRY_KEYVALID( KEY_QUERY_VALUE ))\
  __cregOwner->Refresh();

#define REGENTRY_UPDATE_MULTISTRING \
 LPTSTR lpszBuffer = new _TCHAR[_MAX_REG_VALUE]; \
 REGENTRY_SETLOADING(+); GetMulti(lpszBuffer); REGENTRY_SETLOADING(-); \
 SetMulti(lpszBuffer, MultiLength(true), true); \
 delete [] lpszBuffer;

 
#define REGENTRY_KEYVALID(auto_access) \
 lpszName && ((REGENTRY_AUTO && __cregOwner->AutoOpen(auto_access)) || (!(REGENTRY_AUTO) && __cregOwner->hKey != NULL))

#define REGENTRY_NOTLOADING \
 !(__cregOwner->GetFlags() & CREG_LOADING)

#define REGENTRY_SETLOADING(op) \
 __cregOwner->__dwFlags op= CREG_LOADING

#define REGENTRY_BINARYTOSTRING \
 if (iType == REG_BINARY) { ForceStr(); lpszStr = *this; }

#define REGENTRY_NONCONV_STORAGETYPE(type) \
 CRegEntry& operator=( type &Value ){ REGENTRY_ALLOWCONV(false) SetStruct(Value); return *this; }  \
 operator type(){ type Return; GetStruct(Return); return Return; }

#define REGENTRY_CONV_STORAGETYPE(type, to_sz, from_sz, from_dw, no_result) \
 CRegEntry& operator=( type Value ) { to_sz return (*this = (LPCTSTR)(buffer)); } \
 operator type(){ REGENTRY_BINARYTOSTRING return (REGENTRY_SZ_SAFE ? from_sz :(iType == REG_DWORD ? from_dw : no_result)); }

#define REGENTRY_CONV_NUMERIC_STORAGETYPE(type, maxlen, form, from_sz, from_dw) \
 REGENTRY_CONV_STORAGETYPE(type, _R_BUF(maxlen); _stprintf(buffer, _T(#form), Value);, from_sz, from_dw, 0)


/* ====================================
 * Include CRegEntry Class Definition
 * ==================================== */

#include "RegEntry.h"

/* ====================================
 * Begin CRegistry Class Definition
 * ==================================== */

using namespace std;

class CRegistry {

public:
 
 CRegistry (DWORD flags = CREG_CREATE); 
 virtual  ~CRegistry() { Close(); for (int i=0; i < _reEntries.size(); ++i) delete _reEntries[i]; delete [] _lpszSubKey; }

 CRegEntry& operator[](LPCTSTR lpszVName);
 CRegEntry* GetAt(size_t n) { assert(n < Count());  return _reEntries.at(n); }
 
 bool  Open(LPCTSTR lpszRegPath, HKEY hRootKey = HKEY_LOCAL_MACHINE,
    DWORD dwAccess = KEY_QUERY_VALUE | KEY_SET_VALUE, bool bAuto = false);
 
 bool  AutoOpen(DWORD dwAccess);
 void  AutoClose();
 void  Close();
 bool  Refresh(); 

 static bool KeyExists(LPCTSTR lpszRegPath, HKEY hRootKey = HKEY_LOCAL_MACHINE);
 bool  SubKeyExists(LPCTSTR lpszSub); 
 
 void  DeleteKey(); 

 __inline GetFlags() { return __dwFlags; }
 __inline Count()  { return _reEntries.size(); }
 
 HKEY  hKey;  /* Registry key handle */

protected:
 
 DWORD  __dwFlags;
 friend  void CRegEntry::MultiSetAt(size_t nIndex, LPCTSTR lpszVal);
 friend  void CRegEntry::MultiRemoveAt(size_t nIndex);

private:

 void  InitData(); 
 void  DeleteKey(HKEY hPrimaryKey, LPCTSTR lpszSubKey);

 HKEY  _hRootKey;
 LPTSTR  _lpszSubKey;

 std::vector<CRegEntry *> _reEntries;
};

#pragma warning(pop)

#endif
 

3.Registry.cpp

view plaincopy to clipboardprint?
/*// --- FILE INFORMATION ----------------------------- 
 
  CRegistry.cpp 
  Classes: CRegEntry and CRegistry 
 
  Author:  Stuart Konen 
  Email:   skonen@gmail.com 
 
  Date:    12/1/2004 (MM/DD/YYYY) 
  Version: 1.00 
 
  (-!-) If you're going to use these classes please do not  
  remove these comments... To use these classes, simply #include 
  Registry.h . In MFC you should also turn off precompiled headers 
  for this file, in VC++ this can be done by navigating to: 
 
  Project->Settings->Project Name->CRegistry.cpp->C/C++->Precompiled Headers 
 
*///----------------------------------------------------  
#include "stdafx.h"  
#include "Registry.h"  
 
#ifdef _DEBUG  
#define new DEBUG_NEW  
#undef THIS_FILE  
static char THIS_FILE[] = __FILE__;  
#endif  
 
#pragma warning (disable : 4706)  
 
 
/* =================================================== 
 *  CONSTRUCTOR 
 * =================================================*/ 
 
CRegEntry::CRegEntry(CRegistry *Owner) {  
 
    assert(Owner);  
    InitData(Owner);  
}  
 
 
 
/* =================================================== 
 *  CRegEntry::InitData(CRegistry *Owner) 
 * 
 *  Initializes the entries default values and sets the entries 
 *  owner (CRegistry). This is only called during construction. 
 */ 
 
void CRegEntry::InitData(CRegistry *Owner) {  
      
    dwDWORD = iType = 0;   
    lpszName = lpszStr = NULL;  
      
    __bStored = false;  
    __bConvertable = true;  
    __cregOwner = Owner;      
}  
 
 
 
/* =================================================== 
 *  CRegEntry::ForceStr() 
 * 
 *  Forces the memory allocation for the entry's string value, if it 
 *  has not already been allocated. 
 */ 
 
void CRegEntry::ForceStr() {  
 
    if (lpszStr == NULL) { lpszStr = new _TCHAR[_MAX_REG_VALUE]; lpszStr[0] = 0; }    
}  
 
 
/* =================================================== 
 *  CRegEntry::operator=(LPCTSTR lpszValue) 
 * 
 *  OPERATOR: Assigns a const character array to the open 
 *  registry value. The registry value type will be REG_SZ. 
 */ 
 
CRegEntry& CRegEntry::operator=(LPCTSTR lpszValue) {  
 
    size_t  nValueLen = (_tcslen(lpszValue) + 1)*sizeof(TCHAR);  
    assert(nValueLen <= _MAX_REG_VALUE);  
 
    ForceStr(); iType = REG_SZ;   
    _tcsncpy(lpszStr, lpszValue, nValueLen > _MAX_REG_VALUE ? _MAX_REG_VALUE : nValueLen);  
 
    REGENTRY_ALLOWCONV(true)  
    if (REGENTRY_NOTLOADING && REGENTRY_KEYVALID( KEY_SET_VALUE ))  
        RegSetValueEx(__cregOwner->hKey, lpszName, NULL, REG_SZ, (LPBYTE)lpszValue, nValueLen);  
    REGENTRY_TRYCLOSE;  
 
    __bStored = true;  
 
    return *this;  
}  
 
 
 
/* =================================================== 
 *  CRegEntry::operator=(LPDWORD lpdwValue) 
 * 
 *  OPERATOR: Assigns a DWORD to the open registry value. 
 *  The registry value type will be REG_DWORD. 
 */ 
 
CRegEntry& CRegEntry::operator=(LPDWORD lpdwValue) {  
      
    iType = REG_DWORD;  
    memcpy(&dwDWORD, lpdwValue, sizeof( DWORD ));  
          
    REGENTRY_ALLOWCONV(true)  
    if (REGENTRY_NOTLOADING && REGENTRY_KEYVALID( KEY_SET_VALUE ))  
        RegSetValueEx(__cregOwner->hKey, lpszName, NULL, REG_DWORD, (LPBYTE)&dwDWORD, sizeof( DWORD ));  
    REGENTRY_TRYCLOSE;  
 
    __bStored = true;  
      
    return *this;  
}  
 
 
 
/* =================================================== 
 *  CRegEntry::operator=(CRegEntry& cregValue) 
 * 
 *  OPERATOR: Copys value information from the specified 
 *  registry entry (CRegEntry) into this entry. 
 */ 
 
CRegEntry& CRegEntry::operator=(CRegEntry& cregValue) {  
 
    if (this == &cregValue)  
        return *this;  
      
    if (lpszName == NULL) {  
        size_t nNameLen = _tcslen(cregValue.lpszName) + 1;  
        lpszName = new _TCHAR[nNameLen]; _tcsncpy(lpszName, cregValue.lpszName, nNameLen);  
    }  
      
    switch ((iType = cregValue.iType)) {  
 
        case REG_SZ:  
            return (*this = (ForceStr(), cregValue.lpszStr));  
            break;  
 
        case REG_MULTI_SZ: {  
            LPTSTR lpszBuf = new _TCHAR[_MAX_REG_VALUE];  
            SetMulti(cregValue.GetMulti(lpszBuf), cregValue.MultiLength());  
            delete [] lpszBuf; return *this;  
            }  
            break;  
        case REG_BINARY: {  
            size_t n = cregValue.vBytes.size(); LPBYTE buf = new BYTE[n];  
            cregValue.GetBinary(buf, n); SetBinary(buf, n);  
            delete [] buf; return *this;  
            }  
            break;  
        default:  
            return (*this = cregValue.dwDWORD);  
    }  
}  
 
 
 
/* =================================================== 
 *  CRegEntry::operator LPTSTR() 
 * 
 *  OPERATOR: Converts (if required) and returns the open registry 
 *  value as a null terminated string. 
 */ 
 
CRegEntry::operator LPTSTR() {  
 
    /* If caching is disabled, refresh the entries */ 
    REGENTRY_REFRESH_IF_NOCACHE  
 
    assert(__bConvertable); // Check for conversion implementation  
    ForceStr();  
 
    switch (iType) {  
        case REG_DWORD:  
            _stprintf(lpszStr, _T("%lu"), dwDWORD);  
            break;  
        case REG_MULTI_SZ:  
            GetMulti(lpszStr);  
            break;  
        case REG_BINARY: {  
            _tcsncpy(lpszStr, (const _TCHAR*)&vBytes[0], vBytes.size());  
            lpszStr[vBytes.size()] = 0;  
            }  
            break;  
 
    }  
 
    return lpszStr;  
}  
 
 
 
/* =================================================== 
 *  CRegEntry::operator DWORD() 
 * 
 *  OPERATOR: Converts (if required) and returns the open registry 
 *  value as an unsigned 32-bit integer (unsigned long). 
 */ 
 
CRegEntry::operator DWORD() {  
 
    /* If caching is disabled, refresh the entries */ 
    REGENTRY_REFRESH_IF_NOCACHE  
      
    assert(__bConvertable); // Check for conversion implementation  
 
    REGENTRY_BINARYTOSTRING  
    return (REGENTRY_SZ_SAFE ? _tcstoul(lpszStr, NULL, NULL) : dwDWORD);  
}  
 
 
 
/* =================================================== 
 *  CRegEntry::GetBinary(LPBYTE lpbValue, size_t nLen) 
 * 
 *  Sets the registry value to a binary value (REG_BINARY) 
 * 
 *  Important Params: 
 * 
 *      LPBYTE lpbDest: Pointer to the byte array to store * 
 *      size_t nLen:    Elements contained within the byte array. 
 */ 
 
void CRegEntry::SetBinary(LPBYTE lpbValue, size_t nLen) {  
      
    if (!nLen) { assert(nLen); return; }  
      
    iType = REG_BINARY;   
 
    if (REGENTRY_NOTLOADING && REGENTRY_KEYVALID ( KEY_SET_VALUE ) )  
        RegSetValueEx(__cregOwner->hKey, lpszName, NULL, REG_BINARY, lpbValue, nLen);  
    REGENTRY_TRYCLOSE;  
      
    __bStored = true;  
      
    if (vBytes.size() < nLen) vBytes.reserve(nLen);  
    vBytes.clear();  
          
    do { vBytes.push_back(lpbValue[vBytes.size()]); }  
    while (vBytes.size() < nLen);  
}  
 
 
 
/* =================================================== 
 *  CRegEntry::GetBinary(LPBYTE lpbDest, size_t nMaxLen) 
 * 
 *  Gets the binary value of a value stored as REG_BINARY 
 * 
 *  Important Params: 
 * 
 *      LPBYTE lpbDest: Pointer to the byte array to fill 
 *      size_t nMaxLen: The maximum bytes to copy to lpbDest 
 * 
 *  Notes: This will only work for values that were saved 
 *  using the binary registry type specification (REG_BINARY) 
 */ 
 
void CRegEntry::GetBinary(LPBYTE lpbDest, size_t nMaxLen) {  
 
    assert(IsBinary()); // Must be stored as Binary  
      
    REGENTRY_REFRESH_IF_NOCACHE  
      
    if ((size_t)(&vBytes.back() - &vBytes.at(0)+1) == vBytes.size()*sizeof(BYTE))  
        memcpy(lpbDest, (LPBYTE)&vBytes.at(0), vBytes.size() > nMaxLen ? nMaxLen : vBytes.size());  
    else 
        for (size_t n=0; n < vBytes.size() && n < nMaxLen; n++)  
            lpbDest[n] = vBytes[n];       
}  
 
 
 
/* =================================================== 
 *  CRegEntry::GetBinaryLength()  
 * 
 *  Returns the size of the binary value in bytes. 
 */ 
 
size_t CRegEntry::GetBinaryLength() {  
      
    assert(IsBinary());  
 
    REGENTRY_REFRESH_IF_NOCACHE  
    return vBytes.size();  
}  
 
 
 
/* =================================================== 
 *  CRegEntry::SetMulti(LPCTSTR lpszValue, size_t nLen, bool bInternal) 
 * 
 *  Stores an array of null-terminated string, terminated by two null characters. 
 *  For Example: First String\0Second\Third\0\0 
 * 
 *  Important Params: 
 * 
 *      LPCTSTR lpszValue:  The string consisting of the null-terminated string array 
 *      size_t  nLen:       The number of characters in the string, including null characters 
 * 
 *  Note: For inserting individual null-terminated strings into the array,  
 *  use MultiAdd or MultiSetAt. 
 */ 
 
void CRegEntry::SetMulti(LPCTSTR lpszValue, size_t nLen, bool bInternal) {  
 
    size_t nCur = 0, nPrev = 0, nShortLen = nLen;  
 
    /* When this is internal, there is no need to repopulate the vector. */ 
    if (bInternal) goto SkipNoInternal;  
 
    iType = REG_MULTI_SZ; vMultiString.clear();   
    if (nLen <= 2) goto SkipNoInternal; // The string is empty : \0\0  
    if (*(lpszValue + nShortLen-1) == '\0')  
        nShortLen--;      
 
    /* Populate a vector with each string part for easy and quick access */ 
    while ((nCur = (int)(_tcschr(lpszValue+nPrev, '\0')-lpszValue)) < nShortLen) {         
        vMultiString.push_back(lpszValue+nPrev);  
        nPrev = nCur+1;  
    }  
 
    SkipNoInternal:  
 
    if (REGENTRY_NOTLOADING && REGENTRY_KEYVALID ( KEY_SET_VALUE ) )  
        RegSetValueEx(__cregOwner->hKey, lpszName, NULL, REG_MULTI_SZ, (LPBYTE)lpszValue, nLen*sizeof(TCHAR));  
    REGENTRY_TRYCLOSE;  
 
    __bStored = true;  
}  
 
 
 
/* =================================================== 
 *  CRegEntry::MultiLength(bool bInternal = false) 
 * 
 *  Returns the number of characters (including null) stored  
 *  in the full string. Don't confuse this with MultiCount() 
 *  which returns the number of strings stored in the array. 
 */ 
 
size_t CRegEntry::MultiLength(bool bInternal /*false*/) {  
 
    //Ensure correct values with no cache  
    if (!bInternal) REGENTRY_REFRESH_IF_NOCACHE  
 
    for (size_t nLen = 0, nIndex = 0; nIndex < vMultiString.size(); nIndex++)  
        nLen += vMultiString[nIndex].length() + 1;  
 
    return nLen ? nLen+1 : 0;  
}  
 
 
 
/* =================================================== 
 *  CRegEntry::MultiCount() 
 * 
 *  Returns the number of strings located within the array. 
 */ 
 
size_t CRegEntry::MultiCount() {  
 
    // Ensure correct values with no cache  
    REGENTRY_REFRESH_IF_NOCACHE  
 
    return vMultiString.size();  
}  
 
 
 
/* =================================================== 
 *  CRegEntry::MultiRemoveAt(size_t nIndex) 
 * 
 *  Simply removes the string stored at the zero-based index of nIndex 
 */ 
 
void CRegEntry::MultiRemoveAt(size_t nIndex) {  
 
    // Ensure correct values with no cache  
    REGENTRY_REFRESH_IF_NOCACHE  
 
    assert(nIndex < vMultiString.size());  
    vMultiString.erase(vMultiString.begin()+nIndex);  
 
    // Update the registry  
    REGENTRY_UPDATE_MULTISTRING  
 
}  
 
 
 
/* =================================================== 
 *  CRegEntry::MultiSetAt(size_t nIndex, LPCTSTR lpszVal) 
 * 
 *  Alters the value of a string in the array located at 
 *  the 0 based index of nIndex. The new value is lpszVal. 
 *  The index must be within the bounds of the array, with 
 *  the exception of being == the number of elements in 
 *  which case calling this function is equal to calling 
 *  MultiAdd. 
 */ 
 
void CRegEntry::MultiSetAt(size_t nIndex, LPCTSTR lpszVal) {  
 
    // Ensure correct values with no cache  
    REGENTRY_REFRESH_IF_NOCACHE  
 
    assert(nIndex <= vMultiString.size());  
    iType = REG_MULTI_SZ;  
 
    // Add a new string element if == elements+1  
    if (nIndex == vMultiString.size())    
        vMultiString.push_back(lpszVal);  
    else 
        vMultiString[nIndex] = lpszVal;  
      
    // Update the registry  
    REGENTRY_UPDATE_MULTISTRING  
}  
 
 
 
/* =================================================== 
 *  CRegEntry::MultiGetAt(size_t nIndex) 
 * 
 *  Returns a constant pointer to the string located in 
 *  the array at the zero-based index of nIndex. Note that 
 *  the return value is not an STL string. 
 */ 
 
LPCTSTR CRegEntry::MultiGetAt(size_t nIndex) {  
 
    // Ensure correct values with no cache  
    REGENTRY_REFRESH_IF_NOCACHE   
 
    assert(nIndex < vMultiString.size() && IsMultiString());  
    return vMultiString[nIndex].c_str();  
}  
 
 
 
/* =================================================== 
 *  CRegEntry::GetMulti(LPCTSTR lpszDest, size_t nMax) 
 * 
 *  Copys the entire null-terminated array string to lpszDest. 
 *  For Example: First String\0Second\Third\0\0 
 * 
 *  Important Params: 
 * 
 *      LPCTSTR lpszDest:   Pointer to the character array to fill. 
 *      size_t  nMax:       The maximum characters to read, including null-characters 
 * 
 *  Note: By default nMax is set to _MAX_REG_VALUE, you can retrieve 
 *  the length of the entire string by calling MultiLength(). 
 */ 
 
LPTSTR CRegEntry::GetMulti(LPTSTR lpszDest, size_t nMax) {  
 
    LPCTSTR strBuf;  
    size_t nCur = 0, nLen = 0;  
      
    assert(IsMultiString());  
    if (!IsMultiString()) return &(lpszDest[0] = 0);  
 
    /* If caching is disabled, refresh the entries */ 
    REGENTRY_REFRESH_IF_NOCACHE   
      
    for (size_t n=0; n < vMultiString.size() && nCur < nMax; n++) {  
          
        strBuf = vMultiString[n].c_str();   
        nLen = vMultiString[n].length()+1;  
        _tcsncpy(lpszDest + nCur, strBuf, (nLen >= nMax ? (nMax-nCur) : nLen) * sizeof(_TCHAR));  
        nCur += nLen;  
    }  
 
    /* Add the final null termination */ 
    *(lpszDest + nCur) = 0;  
      
    return lpszDest;  
}  
 
 
/* =================================================== 
 *  CRegEntry::Delete() 
 * 
 *  Removes the value from the open registry key, returns 
 *  true on success and false on failure. 
 */ 
 
bool CRegEntry::Delete() {  
 
    __bStored = false;  
 
    if (REGENTRY_KEYVALID (KEY_SET_VALUE) )  
        return (__cregOwner->AutoClose(), IS_ES(RegDeleteValue(__cregOwner->hKey, lpszName)));  
      
    return false;  
}  
 
 
 
// BEGIN CREGISTRY FUNCTIONS  
   
 
/* =================================================== 
 *  CRegistry CONSTRUCTOR 
 * 
 *  Flags: 
 * 
 *  CREG_CREATE (default) - When attempting to open a key that  
 *  does not exist, create it. 
 * 
 *  CREG_AUTOOPEN - Close the open registry key handle 
 *  after an action has been performed with it. Opens the 
 *  key whenever another action needs to be performed. 
 * 
 * ===================================================*/ 
 
CRegistry::CRegistry(DWORD flags) {   
    InitData(); __dwFlags = flags;   
}  
 
 
 
/* =================================================== 
 *  CRegistry::InitData()  
 *  Initializes the variables related to key locations to NULL. 
 */ 
 
void CRegistry::InitData() {   
 
    _lpszSubKey = NULL;  
    _hRootKey = hKey = NULL;  
}  
 
 
 
/* =================================================== 
 *  CRegistry::operator []( LPCTSTR lpszVName) 
 * 
 *  OPERATOR: This will return the Registry Entry (CRegEntry) associated 
 *  with the given value name. If the value name does not exist in 
 *  the open key, it will be created. 
 * 
 *  Note: If the value name is created, it is only stored in the actual 
 *  registry when the entry's value has been set. 
 */ 
 
CRegEntry& CRegistry::operator []( LPCTSTR lpszVName) {  
      
    size_t nValueNameLen = _tcslen(lpszVName) + 1;  
    assert(nValueNameLen <= _MAX_REG_VALUE);  
 
    for (int i = _reEntries.size()-1; i >=0; i--) {  
        if (!_tcsicmp(lpszVName, _reEntries[i]->lpszName))  
            return *_reEntries[i];  
    }  
      
    /* Entry not found */     
    _reEntries.push_back(new CRegEntry(this));        
    _reEntries.back()->lpszName = new _TCHAR[nValueNameLen];   
    _tcsncpy(_reEntries.back()->lpszName, lpszVName, (nValueNameLen > _MAX_REG_VALUE ? _MAX_REG_VALUE : nValueNameLen));    
 
    return *_reEntries.back();  
}  
 
 
 
/* =================================================== 
 *  CRegistry::KeyExists() 
 * 
 *  Returns true if the key exists and returns false if the key 
 *  does not exist or could not be opened. This may be called 
 *  as a static function. 
 * 
 *  Example:  
 *  CRegistry::KeyExists("Software\\Something", HKEY_LOCAL_MACHINE); 
 */ 
 
bool CRegistry::KeyExists(LPCTSTR lpszRegPath, HKEY hRootKey) {  
      
    CRegistry cregTemp( NULL );  
    return cregTemp.Open(lpszRegPath, hRootKey, KEY_QUERY_VALUE, true);   
}  
 
 
 
/* =================================================== 
 *  CRegistry::SubKeyExists() 
 * 
 *  Returns true if the subkey exists within the currently 
 *  open key and false if not. 
 */ 
 
bool CRegistry::SubKeyExists(LPCTSTR lpszSub) {  
      
    bool bResult;  
    HKEY hTemp;  
 
    if ((__dwFlags & CREG_AUTOOPEN && !AutoOpen(KEY_QUERY_VALUE)) || hKey == NULL) {  
        assert(hKey);  
        return false;  
    }  
 
    bResult = (RegOpenKeyEx(hKey, lpszSub, 0, KEY_QUERY_VALUE, &hTemp) == ERROR_SUCCESS);  
 
    if (bResult) RegCloseKey(hTemp);  
    if (__dwFlags & CREG_AUTOOPEN) AutoClose();  
      
    return bResult;  
}  
 
 
 
/* =================================================== 
 *  CRegistry::Open(LPCTSTR lpszRegPath, HKEY hRootKey, bool bAuto) 
 * 
 *  Opens the key in which values will be read and stored, if the key 
 *  is not already existent in the registry, it will be created (if the 
 *  CREG_CREATE) flag is present while constructing the class. 
 * 
 *  Upon opening the registry key, all of the REG_DWORD and REG_SZ values 
 *  are loaded into a new corresponding CRegEntry for future access. 
 * 
 *  Important Params: 
 * 
 *      LPCTSTR lpszRegPath - A NULL terminated const character array containing, 
 *      the location of the subkey. 
 *      For example: "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run" 
 * 
 *      HKEY hRootKey - An open key handle to the root key. By default 
 *      this value is set as HKEY_LOCAL_MACHINE. 
 *      Another Example: HKEY_CURRENT_USER 
 * 
 *  Returns true on success and false on failure. 
 */ 
 
 
bool CRegistry::Open(LPCTSTR lpszRegPath, HKEY hRootKey, DWORD dwAccess, bool bAuto) {  
 
    bool bNew = true;  
 
 
    /* If the key is being auto opened, skip directly to opening */ 
    if (bAuto) goto SkipNoAuto;   
 
    /* The key is being opened manually, if the key location differs 
    from the last opened location, clear the current entries and 
    store the path information for future auto opening and key 
    deletion using DeleteKey() */     
 
    if (_lpszSubKey){  
 
        if (_tcsicmp(lpszRegPath, _lpszSubKey)) {                 
              
            /* If new key, clear any currently stored entries */ 
            for (size_t n=0; n<_reEntries.size(); n++)  
                delete _reEntries[n];  
 
            _reEntries.clear();  
            delete [] _lpszSubKey;  
 
        } else bNew = false;  
    }  
 
    if (bNew) {  
      
        /* Store path information for auto opening */ 
        _lpszSubKey = new _TCHAR[_tcslen(lpszRegPath)+1];  
        _tcscpy(_lpszSubKey, lpszRegPath);  
    }  
      
    _hRootKey = hRootKey;  
      
      
    SkipNoAuto:  
      
    /* This is where the key is actually opened (if all goes well). 
    If the key does not exist and the CREG_CREATE flag is present, 
    it will be created... Any currently opened key will be closed 
    before opening another one. After opening the key, Refresh() is 
    called and the key's values are stored in memory for future use. */ 
      
    if (hKey != NULL) Close();  
 
 
    /* If auto opening is set and this is a manual opening 
    set the appropriate access rights */ 
 
    if (__dwFlags & CREG_AUTOOPEN && !bAuto) {  
        dwAccess = CREG_CREATE ? KEY_CREATE_SUB_KEY | KEY_QUERY_VALUE : KEY_QUERY_VALUE;  
    }  
 
 
    /* When key creation is enabled and auto opening is disabled, 
    include key creation in the access rights */ 
 
    else if (__dwFlags & ~CREG_AUTOOPEN && __dwFlags & CREG_CREATE)  
        dwAccess |= KEY_CREATE_SUB_KEY;  
 
 
      
    /* Open or create the sub key, and return the result: */ 
    LONG lResult = (__dwFlags & CREG_CREATE ?  
        RegCreateKeyEx(hRootKey, lpszRegPath, 0, NULL, REG_OPTION_NON_VOLATILE, dwAccess, NULL, &hKey, NULL)  
    : RegOpenKeyEx(hRootKey, lpszRegPath, 0, dwAccess, &hKey));  
      
    return (lResult == ERROR_SUCCESS ? (bAuto ? true : Refresh()) : false);  
}  
 
 
 
/* =================================================== 
 *  CRegistry::AutoOpen() 
 *   
 *  If the CREG_AUTOOPEN flag is true, this function is called whenever 
 *  an action needs to be performed involving the registry key. 
 * 
 *  DWORD dwAccess controls the access required for key use. 
 */ 
 
bool CRegistry::AutoOpen(DWORD dwAccess) {  
 
    assert(_lpszSubKey != NULL);      
    return (hKey == NULL && __dwFlags & CREG_AUTOOPEN ? Open(_lpszSubKey, _hRootKey, dwAccess, true) : true);  
}  
 
 
 
/* =================================================== 
 *  CRegistry::AutoClose() 
 *   
 *  If the CREG_AUTOOPEN flag is true, this function is called whenever 
 *  an action has been performed on an open registry key and the key is no longer 
 *  being accessed. 
 */ 
 
void CRegistry::AutoClose() {  
 
    if (__dwFlags & CREG_AUTOOPEN) Close();  
}  
 
 
 
/* =================================================== 
 *  CRegistry::Refresh() 
 *   
 *  Enumerates all the REG_SZ, REG_BINARY and REG_DWORD values within the open 
 *  registry key and stores them in a CRegEntry class for future 
 *  access. Returns true on success and false on failure. 
 */ 
 
bool CRegistry::Refresh() {  
 
    DWORD   dwBufferSize;  
    DWORD   dwType;  
    DWORD   dwNameLen;  
    DWORD   dwValueCount;  
    LPBYTE  lpbBuffer;  
 
    DWORD   dwPrevFlags = __dwFlags;  
    _TCHAR  cValueName[_MAX_PATH];    
 
      
    if ((__dwFlags & CREG_AUTOOPEN && !AutoOpen(KEY_QUERY_VALUE)) || hKey == NULL)  
        return false;  
 
    if (NOT_ES(RegQueryInfoKey(hKey, NULL, NULL, NULL, NULL, NULL, NULL, &dwValueCount, NULL, NULL, NULL, NULL)))  
        return false;  
 
    lpbBuffer = new BYTE[_MAX_REG_VALUE];  
 
 
    /* Halt auto opening and set loading flag */      
    __dwFlags = (__dwFlags | CREG_LOADING) & ~CREG_AUTOOPEN;  
      
 
    if (dwValueCount > _reEntries.size())  
        _reEntries.reserve(dwValueCount);  
 
    for( DWORD dwIndex = 0; dwIndex < dwValueCount; dwIndex++) {  
 
        dwNameLen = sizeof(cValueName); dwBufferSize = _MAX_REG_VALUE;    
        cValueName[0] = 0;  
          
        if (NOT_ES(RegEnumValue(hKey, dwIndex, cValueName, &dwNameLen, NULL, &dwType, lpbBuffer, &dwBufferSize)))  
            continue;  
 
        switch (dwType) {  
                          
            case REG_DWORD:                                               
                this[0][cValueName] = (LPDWORD)lpbBuffer;                 
                break;  
                  
            case REG_SZ:  
                this[0][cValueName] = (LPCTSTR)lpbBuffer;  
                break;                
 
            case REG_MULTI_SZ:  
                this[0][cValueName].SetMulti((LPCTSTR)lpbBuffer, dwBufferSize/sizeof(TCHAR));                 
                break;    
 
            case REG_BINARY:  
                this[0][cValueName].SetBinary(lpbBuffer, (size_t)dwBufferSize);  
                break;                
        }  
    }  
 
    if ((__dwFlags = dwPrevFlags) & CREG_AUTOOPEN) AutoClose();  
    delete [] lpbBuffer;  
 
    return true;  
}  
 
 
 
/* =================================================== 
 *  CRegistry::DeleteKey() 
 *   
 *  Deletes the key which is currently opened, including any 
 *  subkeys and values it may contain. 
 * 
 *  NOTE: Use extreme caution when calling this function 
 */ 
 
void CRegistry::DeleteKey() {  
 
    OSVERSIONINFO osvi;  
    osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);  
      
    if (GetVersionEx(&osvi) && osvi.dwPlatformId == VER_PLATFORM_WIN32_NT)  
        DeleteKey(_hRootKey, _lpszSubKey);  
    else   
        RegDeleteKey(_hRootKey, _lpszSubKey);  
 
    Close();  
}  
 
 
 
/* =================================================== 
 *  CRegistry::DeleteKey(HKEY hPrimaryKey, LPCTSTR lpszSubKey) 
 *   
 *  Private member function which is called by DeleteKey() 
 *  This function is designed for NT based systems as it recursively 
 *  deletes any subkeys present. 
 */ 
 
void CRegistry::DeleteKey(HKEY hPrimaryKey, LPCTSTR lpszSubKey) {  
 
    DWORD dwKeyLen;  
    FILETIME ftTemp;  
    HKEY hTempKey;  
 
    LONG   lResult = ERROR_SUCCESS;  
    LPTSTR lpszKey = new _TCHAR[_MAX_PATH];   
 
    if (!_tcslen(lpszSubKey) || !hPrimaryKey) { assert(hPrimaryKey != NULL); goto cleanup; }  
 
    if (IS_ES(RegOpenKeyEx(hPrimaryKey, lpszSubKey, 0, KEY_ENUMERATE_SUB_KEYS | KEY_WRITE, &hTempKey))){  
          
        while (IS_ES(lResult)) {  
              
            dwKeyLen = _MAX_PATH;  
            lResult  = RegEnumKeyEx(hTempKey, 0, lpszKey, &dwKeyLen, NULL, NULL, NULL, &ftTemp);  
 
            if (lResult == ERROR_SUCCESS) DeleteKey(hTempKey, lpszKey);  
            else if (lResult == ERROR_NO_MORE_ITEMS) RegDeleteKey(hPrimaryKey, lpszSubKey);  
        }  
        RegCloseKey(hTempKey); hTempKey = NULL;  
    }  
 
    cleanup: delete [] lpszKey;            
}  
 
 
 
/* =================================================== 
 *  CRegistry::Close() 
 * 
 *  If a key is currently open, it will be closed. This should 
 *  be called when you no longer need to access the registry key 
 *  and the CREG_AUTOOPEN flag is not true. However, Close() is  
 *  called on class deconstruction so it is not required. 
 */ 
 
void CRegistry::Close() {  
 
    if (hKey != NULL) {   
        RegCloseKey(hKey); hKey = NULL;   
    }  

/*// --- FILE INFORMATION -----------------------------

  CRegistry.cpp
  Classes: CRegEntry and CRegistry

  Author:  Stuart Konen
  Email:   skonen@gmail.com

  Date:    12/1/2004 (MM/DD/YYYY)
  Version: 1.00

  (-!-) If you're going to use these classes please do not
  remove these comments... To use these classes, simply #include
  Registry.h . In MFC you should also turn off precompiled headers
  for this file, in VC++ this can be done by navigating to:

  Project->Settings->Project Name->CRegistry.cpp->C/C++->Precompiled Headers

*///----------------------------------------------------
#include "stdafx.h"
#include "Registry.h"

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

#pragma warning (disable : 4706)


/* ===================================================
 * CONSTRUCTOR
 * =================================================*/

CRegEntry::CRegEntry(CRegistry *Owner) {

 assert(Owner);
 InitData(Owner);
}

 

/* ===================================================
 *  CRegEntry::InitData(CRegistry *Owner)
 *
 *  Initializes the entries default values and sets the entries
 *  owner (CRegistry). This is only called during construction.
 */

void CRegEntry::InitData(CRegistry *Owner) {
 
 dwDWORD = iType = 0;
 lpszName = lpszStr = NULL;
 
 __bStored = false;
 __bConvertable = true;
 __cregOwner = Owner; 
}

 

/* ===================================================
 *  CRegEntry::ForceStr()
 *
 *  Forces the memory allocation for the entry's string value, if it
 *  has not already been allocated.
 */

void CRegEntry::ForceStr() {

 if (lpszStr == NULL) { lpszStr = new _TCHAR[_MAX_REG_VALUE]; lpszStr[0] = 0; } 
}


/* ===================================================
 *  CRegEntry::operator=(LPCTSTR lpszValue)
 *
 *  OPERATOR: Assigns a const character array to the open
 *  registry value. The registry value type will be REG_SZ.
 */

CRegEntry& CRegEntry::operator=(LPCTSTR lpszValue) {

 size_t nValueLen = (_tcslen(lpszValue) + 1)*sizeof(TCHAR);
 assert(nValueLen <= _MAX_REG_VALUE);

 ForceStr(); iType = REG_SZ; 
 _tcsncpy(lpszStr, lpszValue, nValueLen > _MAX_REG_VALUE ? _MAX_REG_VALUE : nValueLen);

 REGENTRY_ALLOWCONV(true)
 if (REGENTRY_NOTLOADING && REGENTRY_KEYVALID( KEY_SET_VALUE ))
  RegSetValueEx(__cregOwner->hKey, lpszName, NULL, REG_SZ, (LPBYTE)lpszValue, nValueLen);
 REGENTRY_TRYCLOSE;

 __bStored = true;

 return *this;
}

 

/* ===================================================
 *  CRegEntry::operator=(LPDWORD lpdwValue)
 *
 *  OPERATOR: Assigns a DWORD to the open registry value.
 *  The registry value type will be REG_DWORD.
 */

CRegEntry& CRegEntry::operator=(LPDWORD lpdwValue) {
 
 iType = REG_DWORD;
 memcpy(&dwDWORD, lpdwValue, sizeof( DWORD ));
  
 REGENTRY_ALLOWCONV(true)
 if (REGENTRY_NOTLOADING && REGENTRY_KEYVALID( KEY_SET_VALUE ))
  RegSetValueEx(__cregOwner->hKey, lpszName, NULL, REG_DWORD, (LPBYTE)&dwDWORD, sizeof( DWORD ));
 REGENTRY_TRYCLOSE;

 __bStored = true;
 
 return *this;
}

 

/* ===================================================
 *  CRegEntry::operator=(CRegEntry& cregValue)
 *
 *  OPERATOR: Copys value information from the specified
 * registry entry (CRegEntry) into this entry.
 */

CRegEntry& CRegEntry::operator=(CRegEntry& cregValue) {

 if (this == &cregValue)
  return *this;
 
 if (lpszName == NULL) {
  size_t nNameLen = _tcslen(cregValue.lpszName) + 1;
  lpszName = new _TCHAR[nNameLen]; _tcsncpy(lpszName, cregValue.lpszName, nNameLen);
 }
 
 switch ((iType = cregValue.iType)) {

  case REG_SZ:
   return (*this = (ForceStr(), cregValue.lpszStr));
   break;

  case REG_MULTI_SZ: {
   LPTSTR lpszBuf = new _TCHAR[_MAX_REG_VALUE];
   SetMulti(cregValue.GetMulti(lpszBuf), cregValue.MultiLength());
   delete [] lpszBuf; return *this;
   }
   break;
  case REG_BINARY: {
   size_t n = cregValue.vBytes.size(); LPBYTE buf = new BYTE[n];
   cregValue.GetBinary(buf, n); SetBinary(buf, n);
   delete [] buf; return *this;
   }
   break;
  default:
   return (*this = cregValue.dwDWORD);
 }
}

 

/* ===================================================
 *  CRegEntry::operator LPTSTR()
 *
 *  OPERATOR: Converts (if required) and returns the open registry
 *  value as a null terminated string.
 */

CRegEntry::operator LPTSTR() {

 /* If caching is disabled, refresh the entries */
 REGENTRY_REFRESH_IF_NOCACHE

 assert(__bConvertable); // Check for conversion implementation
 ForceStr();

 switch (iType) {
  case REG_DWORD:
   _stprintf(lpszStr, _T("%lu"), dwDWORD);
   break;
  case REG_MULTI_SZ:
   GetMulti(lpszStr);
   break;
  case REG_BINARY: {
   _tcsncpy(lpszStr, (const _TCHAR*)&vBytes[0], vBytes.size());
   lpszStr[vBytes.size()] = 0;
   }
   break;

 }

 return lpszStr;
}

 

/* ===================================================
 *  CRegEntry::operator DWORD()
 *
 *  OPERATOR: Converts (if required) and returns the open registry
 *  value as an unsigned 32-bit integer (unsigned long).
 */

CRegEntry::operator DWORD() {

 /* If caching is disabled, refresh the entries */
 REGENTRY_REFRESH_IF_NOCACHE
 
 assert(__bConvertable); // Check for conversion implementation

 REGENTRY_BINARYTOSTRING
 return (REGENTRY_SZ_SAFE ? _tcstoul(lpszStr, NULL, NULL) : dwDWORD);
}

 

/* ===================================================
 *  CRegEntry::GetBinary(LPBYTE lpbValue, size_t nLen)
 *
 * Sets the registry value to a binary value (REG_BINARY)
 *
 *  Important Params:
 *
 *  LPBYTE lpbDest: Pointer to the byte array to store *
 *  size_t nLen: Elements contained within the byte array.
 */

void CRegEntry::SetBinary(LPBYTE lpbValue, size_t nLen) {
 
 if (!nLen) { assert(nLen); return; }
 
 iType = REG_BINARY; 

 if (REGENTRY_NOTLOADING && REGENTRY_KEYVALID ( KEY_SET_VALUE ) )
  RegSetValueEx(__cregOwner->hKey, lpszName, NULL, REG_BINARY, lpbValue, nLen);
 REGENTRY_TRYCLOSE;
 
 __bStored = true;
 
 if (vBytes.size() < nLen) vBytes.reserve(nLen);
 vBytes.clear();
  
 do { vBytes.push_back(lpbValue[vBytes.size()]); }
 while (vBytes.size() < nLen);
}

 

/* ===================================================
 *  CRegEntry::GetBinary(LPBYTE lpbDest, size_t nMaxLen)
 *
 * Gets the binary value of a value stored as REG_BINARY
 *
 *  Important Params:
 *
 *  LPBYTE lpbDest: Pointer to the byte array to fill
 *  size_t nMaxLen: The maximum bytes to copy to lpbDest
 *
 * Notes: This will only work for values that were saved
 * using the binary registry type specification (REG_BINARY)
 */

void CRegEntry::GetBinary(LPBYTE lpbDest, size_t nMaxLen) {

 assert(IsBinary()); // Must be stored as Binary
 
 REGENTRY_REFRESH_IF_NOCACHE
 
 if ((size_t)(&vBytes.back() - &vBytes.at(0)+1) == vBytes.size()*sizeof(BYTE))
  memcpy(lpbDest, (LPBYTE)&vBytes.at(0), vBytes.size() > nMaxLen ? nMaxLen : vBytes.size());
 else
  for (size_t n=0; n < vBytes.size() && n < nMaxLen; n++)
   lpbDest[n] = vBytes[n];  
}

 

/* ===================================================
 * CRegEntry::GetBinaryLength()
 *
 * Returns the size of the binary value in bytes.
 */

size_t CRegEntry::GetBinaryLength() {
 
 assert(IsBinary());

 REGENTRY_REFRESH_IF_NOCACHE
 return vBytes.size();
}

 

/* ===================================================
 *  CRegEntry::SetMulti(LPCTSTR lpszValue, size_t nLen, bool bInternal)
 *
 * Stores an array of null-terminated string, terminated by two null characters.
 * For Example: First String\0Second\Third\0\0
 *
 *  Important Params:
 *
 *  LPCTSTR lpszValue: The string consisting of the null-terminated string array
 *  size_t  nLen:  The number of characters in the string, including null characters
 *
 * Note: For inserting individual null-terminated strings into the array,
 * use MultiAdd or MultiSetAt.
 */

void CRegEntry::SetMulti(LPCTSTR lpszValue, size_t nLen, bool bInternal) {

 size_t nCur = 0, nPrev = 0, nShortLen = nLen;

 /* When this is internal, there is no need to repopulate the vector. */
 if (bInternal) goto SkipNoInternal;

 iType = REG_MULTI_SZ; vMultiString.clear(); 
 if (nLen <= 2) goto SkipNoInternal; // The string is empty : \0\0
 if (*(lpszValue + nShortLen-1) == '\0')
  nShortLen--; 

 /* Populate a vector with each string part for easy and quick access */
 while ((nCur = (int)(_tcschr(lpszValue+nPrev, '\0')-lpszValue)) < nShortLen) {  
  vMultiString.push_back(lpszValue+nPrev);
  nPrev = nCur+1;
 }

 SkipNoInternal:

 if (REGENTRY_NOTLOADING && REGENTRY_KEYVALID ( KEY_SET_VALUE ) )
  RegSetValueEx(__cregOwner->hKey, lpszName, NULL, REG_MULTI_SZ, (LPBYTE)lpszValue, nLen*sizeof(TCHAR));
 REGENTRY_TRYCLOSE;

 __bStored = true;
}

 

/* ===================================================
 *  CRegEntry::MultiLength(bool bInternal = false)
 *
 * Returns the number of characters (including null) stored
 * in the full string. Don't confuse this with MultiCount()
 * which returns the number of strings stored in the array.
 */

size_t CRegEntry::MultiLength(bool bInternal /*false*/) {

 //Ensure correct values with no cache
 if (!bInternal) REGENTRY_REFRESH_IF_NOCACHE

 for (size_t nLen = 0, nIndex = 0; nIndex < vMultiString.size(); nIndex++)
  nLen += vMultiString[nIndex].length() + 1;

 return nLen ? nLen+1 : 0;
}

 

/* ===================================================
 *  CRegEntry::MultiCount()
 *
 * Returns the number of strings located within the array.
 */

size_t CRegEntry::MultiCount() {

 // Ensure correct values with no cache
 REGENTRY_REFRESH_IF_NOCACHE

 return vMultiString.size();
}

 

/* ===================================================
 *  CRegEntry::MultiRemoveAt(size_t nIndex)
 *
 * Simply removes the string stored at the zero-based index of nIndex
 */

void CRegEntry::MultiRemoveAt(size_t nIndex) {

 // Ensure correct values with no cache
 REGENTRY_REFRESH_IF_NOCACHE

 assert(nIndex < vMultiString.size());
 vMultiString.erase(vMultiString.begin()+nIndex);

 // Update the registry
 REGENTRY_UPDATE_MULTISTRING

}

 

/* ===================================================
 *  CRegEntry::MultiSetAt(size_t nIndex, LPCTSTR lpszVal)
 *
 * Alters the value of a string in the array located at
 *  the 0 based index of nIndex. The new value is lpszVal.
 * The index must be within the bounds of the array, with
 * the exception of being == the number of elements in
 * which case calling this function is equal to calling
 * MultiAdd.
 */

void CRegEntry::MultiSetAt(size_t nIndex, LPCTSTR lpszVal) {

 // Ensure correct values with no cache
 REGENTRY_REFRESH_IF_NOCACHE

 assert(nIndex <= vMultiString.size());
 iType = REG_MULTI_SZ;

 // Add a new string element if == elements+1
 if (nIndex == vMultiString.size()) 
  vMultiString.push_back(lpszVal);
 else
  vMultiString[nIndex] = lpszVal;
 
 // Update the registry
 REGENTRY_UPDATE_MULTISTRING
}

 

/* ===================================================
 *  CRegEntry::MultiGetAt(size_t nIndex)
 *
 * Returns a constant pointer to the string located in
 * the array at the zero-based index of nIndex. Note that
 * the return value is not an STL string.
 */

LPCTSTR CRegEntry::MultiGetAt(size_t nIndex) {

 // Ensure correct values with no cache
 REGENTRY_REFRESH_IF_NOCACHE 

 assert(nIndex < vMultiString.size() && IsMultiString());
 return vMultiString[nIndex].c_str();
}

 

/* ===================================================
 *  CRegEntry::GetMulti(LPCTSTR lpszDest, size_t nMax)
 *
 * Copys the entire null-terminated array string to lpszDest.
 * For Example: First String\0Second\Third\0\0
 *
 *  Important Params:
 *
 *  LPCTSTR lpszDest: Pointer to the character array to fill.
 *  size_t  nMax:  The maximum characters to read, including null-characters
 *
 * Note: By default nMax is set to _MAX_REG_VALUE, you can retrieve
 * the length of the entire string by calling MultiLength().
 */

LPTSTR CRegEntry::GetMulti(LPTSTR lpszDest, size_t nMax) {

 LPCTSTR strBuf;
 size_t nCur = 0, nLen = 0;
 
 assert(IsMultiString());
 if (!IsMultiString()) return &(lpszDest[0] = 0);

 /* If caching is disabled, refresh the entries */
 REGENTRY_REFRESH_IF_NOCACHE 
 
 for (size_t n=0; n < vMultiString.size() && nCur < nMax; n++) {
  
  strBuf = vMultiString[n].c_str();
  nLen = vMultiString[n].length()+1;
  _tcsncpy(lpszDest + nCur, strBuf, (nLen >= nMax ? (nMax-nCur) : nLen) * sizeof(_TCHAR));
  nCur += nLen;
 }

 /* Add the final null termination */
 *(lpszDest + nCur) = 0;
 
 return lpszDest;
}


/* ===================================================
 *  CRegEntry::Delete()
 *
 * Removes the value from the open registry key, returns
 *  true on success and false on failure.
 */

bool CRegEntry::Delete() {

 __bStored = false;

 if (REGENTRY_KEYVALID (KEY_SET_VALUE) )
  return (__cregOwner->AutoClose(), IS_ES(RegDeleteValue(__cregOwner->hKey, lpszName)));
 
 return false;
}

 

// BEGIN CREGISTRY FUNCTIONS
 

/* ===================================================
 *  CRegistry CONSTRUCTOR
 *
 *  Flags:
 *
 * CREG_CREATE (default) - When attempting to open a key that
 *  does not exist, create it.
 *
 * CREG_AUTOOPEN - Close the open registry key handle
 * after an action has been performed with it. Opens the
 * key whenever another action needs to be performed.
 *
 * ===================================================*/

CRegistry::CRegistry(DWORD flags) { 
 InitData(); __dwFlags = flags;
}

 

/* ===================================================
 *  CRegistry::InitData()
 *  Initializes the variables related to key locations to NULL.
 */

void CRegistry::InitData() {

 _lpszSubKey = NULL;
 _hRootKey = hKey = NULL;
}

 

/* ===================================================
 *  CRegistry::operator []( LPCTSTR lpszVName)
 *
 *  OPERATOR: This will return the Registry Entry (CRegEntry) associated
 *  with the given value name. If the value name does not exist in
 *  the open key, it will be created.
 *
 *  Note: If the value name is created, it is only stored in the actual
 *  registry when the entry's value has been set.
 */

CRegEntry& CRegistry::operator []( LPCTSTR lpszVName) {
 
 size_t nValueNameLen = _tcslen(lpszVName) + 1;
 assert(nValueNameLen <= _MAX_REG_VALUE);

 for (int i = _reEntries.size()-1; i >=0; i--) {
  if (!_tcsicmp(lpszVName, _reEntries[i]->lpszName))
   return *_reEntries[i];
 }
 
 /* Entry not found */ 
 _reEntries.push_back(new CRegEntry(this));  
 _reEntries.back()->lpszName = new _TCHAR[nValueNameLen]; 
 _tcsncpy(_reEntries.back()->lpszName, lpszVName, (nValueNameLen > _MAX_REG_VALUE ? _MAX_REG_VALUE : nValueNameLen)); 

 return *_reEntries.back();
}

 

/* ===================================================
 *  CRegistry::KeyExists()
 *
 * Returns true if the key exists and returns false if the key
 * does not exist or could not be opened. This may be called
 * as a static function.
 *
 * Example:
 * CRegistry::KeyExists("Software\\Something", HKEY_LOCAL_MACHINE);
 */

bool CRegistry::KeyExists(LPCTSTR lpszRegPath, HKEY hRootKey) {
 
 CRegistry cregTemp( NULL );
 return cregTemp.Open(lpszRegPath, hRootKey, KEY_QUERY_VALUE, true); 
}

 

/* ===================================================
 *  CRegistry::SubKeyExists()
 *
 * Returns true if the subkey exists within the currently
 * open key and false if not.
 */

bool CRegistry::SubKeyExists(LPCTSTR lpszSub) {
 
 bool bResult;
 HKEY hTemp;

 if ((__dwFlags & CREG_AUTOOPEN && !AutoOpen(KEY_QUERY_VALUE)) || hKey == NULL) {
  assert(hKey);
  return false;
 }

 bResult = (RegOpenKeyEx(hKey, lpszSub, 0, KEY_QUERY_VALUE, &hTemp) == ERROR_SUCCESS);

 if (bResult) RegCloseKey(hTemp);
 if (__dwFlags & CREG_AUTOOPEN) AutoClose();
 
 return bResult;
}

 

/* ===================================================
 *  CRegistry::Open(LPCTSTR lpszRegPath, HKEY hRootKey, bool bAuto)
 *
 *  Opens the key in which values will be read and stored, if the key
 *  is not already existent in the registry, it will be created (if the
 *  CREG_CREATE) flag is present while constructing the class.
 *
 *  Upon opening the registry key, all of the REG_DWORD and REG_SZ values
 *  are loaded into a new corresponding CRegEntry for future access.
 *
 *  Important Params:
 *
 *  LPCTSTR lpszRegPath - A NULL terminated const character array containing,
 *  the location of the subkey.
 *  For example: "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run"
 *
 *  HKEY hRootKey - An open key handle to the root key. By default
 *  this value is set as HKEY_LOCAL_MACHINE.
 *  Another Example: HKEY_CURRENT_USER
 *
 * Returns true on success and false on failure.
 */


bool CRegistry::Open(LPCTSTR lpszRegPath, HKEY hRootKey, DWORD dwAccess, bool bAuto) {

 bool bNew = true;


 /* If the key is being auto opened, skip directly to opening */
 if (bAuto) goto SkipNoAuto; 

 /* The key is being opened manually, if the key location differs
 from the last opened location, clear the current entries and
 store the path information for future auto opening and key
 deletion using DeleteKey() */ 

 if (_lpszSubKey){

  if (_tcsicmp(lpszRegPath, _lpszSubKey)) {    
   
   /* If new key, clear any currently stored entries */
   for (size_t n=0; n<_reEntries.size(); n++)
    delete _reEntries[n];

   _reEntries.clear();
   delete [] _lpszSubKey;

  } else bNew = false;
 }

 if (bNew) {
 
  /* Store path information for auto opening */
  _lpszSubKey = new _TCHAR[_tcslen(lpszRegPath)+1];
  _tcscpy(_lpszSubKey, lpszRegPath);
 }
 
 _hRootKey = hRootKey;
 
 
 SkipNoAuto:
 
 /* This is where the key is actually opened (if all goes well).
 If the key does not exist and the CREG_CREATE flag is present,
 it will be created... Any currently opened key will be closed
 before opening another one. After opening the key, Refresh() is
 called and the key's values are stored in memory for future use. */
 
 if (hKey != NULL) Close();


 /* If auto opening is set and this is a manual opening
 set the appropriate access rights */

 if (__dwFlags & CREG_AUTOOPEN && !bAuto) {
  dwAccess = CREG_CREATE ? KEY_CREATE_SUB_KEY | KEY_QUERY_VALUE : KEY_QUERY_VALUE;
 }


 /* When key creation is enabled and auto opening is disabled,
 include key creation in the access rights */

 else if (__dwFlags & ~CREG_AUTOOPEN && __dwFlags & CREG_CREATE)
  dwAccess |= KEY_CREATE_SUB_KEY;


 
 /* Open or create the sub key, and return the result: */
 LONG lResult = (__dwFlags & CREG_CREATE ?
  RegCreateKeyEx(hRootKey, lpszRegPath, 0, NULL, REG_OPTION_NON_VOLATILE, dwAccess, NULL, &hKey, NULL)
 : RegOpenKeyEx(hRootKey, lpszRegPath, 0, dwAccess, &hKey));
 
 return (lResult == ERROR_SUCCESS ? (bAuto ? true : Refresh()) : false);
}

 

/* ===================================================
 *  CRegistry::AutoOpen()
 * 
 * If the CREG_AUTOOPEN flag is true, this function is called whenever
 * an action needs to be performed involving the registry key.
 *
 * DWORD dwAccess controls the access required for key use.
 */

bool CRegistry::AutoOpen(DWORD dwAccess) {

 assert(_lpszSubKey != NULL); 
 return (hKey == NULL && __dwFlags & CREG_AUTOOPEN ? Open(_lpszSubKey, _hRootKey, dwAccess, true) : true);
}

 

/* ===================================================
 *  CRegistry::AutoClose()
 * 
 * If the CREG_AUTOOPEN flag is true, this function is called whenever
 * an action has been performed on an open registry key and the key is no longer
 * being accessed.
 */

void CRegistry::AutoClose() {

 if (__dwFlags & CREG_AUTOOPEN) Close();
}

 

/* ===================================================
 *  CRegistry::Refresh()
 * 
 * Enumerates all the REG_SZ, REG_BINARY and REG_DWORD values within the open
 * registry key and stores them in a CRegEntry class for future
 *  access. Returns true on success and false on failure.
 */

bool CRegistry::Refresh() {

 DWORD dwBufferSize;
 DWORD dwType;
 DWORD dwNameLen;
 DWORD dwValueCount;
 LPBYTE  lpbBuffer;

 DWORD dwPrevFlags = __dwFlags;
 _TCHAR cValueName[_MAX_PATH]; 

 
 if ((__dwFlags & CREG_AUTOOPEN && !AutoOpen(KEY_QUERY_VALUE)) || hKey == NULL)
  return false;

 if (NOT_ES(RegQueryInfoKey(hKey, NULL, NULL, NULL, NULL, NULL, NULL, &dwValueCount, NULL, NULL, NULL, NULL)))
  return false;

 lpbBuffer = new BYTE[_MAX_REG_VALUE];


 /* Halt auto opening and set loading flag */ 
 __dwFlags = (__dwFlags | CREG_LOADING) & ~CREG_AUTOOPEN;
 

 if (dwValueCount > _reEntries.size())
  _reEntries.reserve(dwValueCount);

 for( DWORD dwIndex = 0; dwIndex < dwValueCount; dwIndex++) {

  dwNameLen = sizeof(cValueName); dwBufferSize = _MAX_REG_VALUE; 
  cValueName[0] = 0;
  
  if (NOT_ES(RegEnumValue(hKey, dwIndex, cValueName, &dwNameLen, NULL, &dwType, lpbBuffer, &dwBufferSize)))
   continue;

  switch (dwType) {
      
   case REG_DWORD:            
    this[0][cValueName] = (LPDWORD)lpbBuffer;    
    break;
    
   case REG_SZ:
    this[0][cValueName] = (LPCTSTR)lpbBuffer;
    break;    

   case REG_MULTI_SZ:
    this[0][cValueName].SetMulti((LPCTSTR)lpbBuffer, dwBufferSize/sizeof(TCHAR));    
    break; 

   case REG_BINARY:
    this[0][cValueName].SetBinary(lpbBuffer, (size_t)dwBufferSize);
    break;    
  }
 }

 if ((__dwFlags = dwPrevFlags) & CREG_AUTOOPEN) AutoClose();
 delete [] lpbBuffer;

 return true;
}

 

/* ===================================================
 *  CRegistry::DeleteKey()
 * 
 * Deletes the key which is currently opened, including any
 *  subkeys and values it may contain.
 *
 *  NOTE: Use extreme caution when calling this function
 */

void CRegistry::DeleteKey() {

 OSVERSIONINFO osvi;
 osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
 
 if (GetVersionEx(&osvi) && osvi.dwPlatformId == VER_PLATFORM_WIN32_NT)
  DeleteKey(_hRootKey, _lpszSubKey);
 else
  RegDeleteKey(_hRootKey, _lpszSubKey);

 Close();
}

 

/* ===================================================
 * CRegistry::DeleteKey(HKEY hPrimaryKey, LPCTSTR lpszSubKey)
 * 
 * Private member function which is called by DeleteKey()
 * This function is designed for NT based systems as it recursively
 * deletes any subkeys present.
 */

void CRegistry::DeleteKey(HKEY hPrimaryKey, LPCTSTR lpszSubKey) {

 DWORD dwKeyLen;
 FILETIME ftTemp;
 HKEY hTempKey;

 LONG   lResult = ERROR_SUCCESS;
 LPTSTR lpszKey = new _TCHAR[_MAX_PATH]; 

 if (!_tcslen(lpszSubKey) || !hPrimaryKey) { assert(hPrimaryKey != NULL); goto cleanup; }

 if (IS_ES(RegOpenKeyEx(hPrimaryKey, lpszSubKey, 0, KEY_ENUMERATE_SUB_KEYS | KEY_WRITE, &hTempKey))){
  
  while (IS_ES(lResult)) {
   
   dwKeyLen = _MAX_PATH;
   lResult  = RegEnumKeyEx(hTempKey, 0, lpszKey, &dwKeyLen, NULL, NULL, NULL, &ftTemp);

   if (lResult == ERROR_SUCCESS) DeleteKey(hTempKey, lpszKey);
   else if (lResult == ERROR_NO_MORE_ITEMS) RegDeleteKey(hPrimaryKey, lpszSubKey);
  }
  RegCloseKey(hTempKey); hTempKey = NULL;
 }

 cleanup: delete [] lpszKey;   
}

 

/* ===================================================
 *  CRegistry::Close()
 *
 *  If a key is currently open, it will be closed. This should
 *  be called when you no longer need to access the registry key
 *  and the CREG_AUTOOPEN flag is not true. However, Close() is
 *  called on class deconstruction so it is not required.
 */

void CRegistry::Close() {

 if (hKey != NULL) {
  RegCloseKey(hKey); hKey = NULL;
 }
}

   (二)具体实施方案

1.把以上的三个文件加入到你的工程中去;

2.在MainFrm.cpp中包含相关的头文件

#include "Registry.h"
#include "RegEntry.h"

3.在MainFrm的析构函数中执行注册表的信息清理工作:

    首先,获取本程序自定义的文档类型。我在网上没找着相应的解决方案,于是自己根据mfc的api自己编了一个,希望大家不要见笑,更希望大家能够提供更好的解决方案。

POSITION doc_position;
 doc_position = AfxGetApp()->GetFirstDocTemplatePosition();
 CString type;
 AfxGetApp()->GetNextDocTemplate(doc_position)->GetDocString(type,CDocTemplate::filterExt);


      然后,使用上述的封装类类删除由EnableShellOpen();RegisterShellFileTypes(TRUE);自动生成的注册表信息。主要有两项:一个以自定义的文档类型名称来命名的节点,另一个是以前一个节点的具体值来命名的节点。具体代码如下:

CRegistry reg(0 & ~CREG_CREATE),reg2(0 & ~CREG_CREATE);
 CString info;
 if(reg.Open(type,HKEY_CLASSES_ROOT)){
  if (reg.GetAt(0)->Exists()){  
   if(reg.GetAt(0)->IsString())
    info.Format("%s",reg.GetAt(0)->operator LPTSTR());
  }
  if(reg2.Open(info,HKEY_CLASSES_ROOT)){
   reg2.DeleteKey();
   reg.DeleteKey();
  }
 }


OK,现就到这里吧。有什么问题希望大家能够留下宝贵的意见。


本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/wirror800/archive/2009/03/23/4017886.aspx

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多