文章目录
Header file
 /**
 * @file      xRegistry.h
 * @date      2012 5.18/周六 14:20:32
 * @author    lei email:[email protected]
 * @copyright GNU Public License.
 * @remark    注册表编辑
 */
#ifndef AFX_XREGISTRY_H__98332335_740E_4E47_8F08_0689B508E55B__INCLUDED_
#define AFX_XREGISTRY_H__98332335_740E_4E47_8F08_0689B508E55B__INCLUDED_

#include <tchar.h>
#include <vector>
#ifdef __AFXWIN_H__
#include <afxtempl.h> //方便使用CStringArray
#endif

class Registry
{
    typedef struct _RegItem {
        TCHAR szItemName[256];
        unsigned char* pValueBuf;
        unsigned long dwValBufLen;
    } RegItem;

public:
    // defroot: HKEY_CURRENT_USER(0x80000001)
    Registry(const TCHAR* lpDefKeyName=_T("Software\\leizi"), void* hDefRootKey=(void*)0x80000001);
    virtual ~Registry();
    bool  SetRootKey(void* hRootKey=(void*)0x80000001);
    bool  OpenKey(const TCHAR* lpRegKey,bool bCreateIfNoExist=false);
    void  GetKey(TCHAR* lpszRegKey/*OUT*/, void* *phRootKey/*OUT*/);
    bool  SetValue(const TCHAR* lpItem,void *pValue,unsigned long dwLen=sizeof(unsigned long),unsigned long dwType=4); //REG_DWORD
    bool  GetValue(const TCHAR* lpItem,void *pValue,unsigned long *pdwLen=NULL,unsigned long *pdwType=NULL) ;
    bool  DelValue(const TCHAR* lpItem) ;
    // exepath为空时表当前程序的全路径
    void  SetAutoRunOnBoot(TCHAR* pStartName,bool bRunFlag,TCHAR* pExeFullPath=NULL);

    // RegItems由使用者释放(free)
    bool  EnumKeyValues(std::vector<RegItem*>& arrValues,const TCHAR* lpRegKey=NULL);
#ifdef UNICODE
    bool  EnumSubkeys(std::vector<std::wstring>& arrSubkeys,const TCHAR* lpRegKey=NULL);
#else
    bool  EnumSubkeys(std::vector<std::string>& arrSubkeys,const TCHAR* lpRegKey=NULL);
#endif
#ifdef __AFXWIN_H__
    bool  EnumKeyValues(CArray<RegItem*,RegItem*> &arrValues,const TCHAR* lpRegKey=NULL);
    bool  EnumSubkeys(CStringArray &arrSubkeys,const TCHAR* lpRegKey=NULL);
#endif
    void  FreeRegItem(void *pItem);
//////////////////////////////////////////////////////////////////////////
private:
    void* m_hKeyOpened ;
    void* m_hRootKey ;
    TCHAR m_szOpenedKey[1024];
};

#endif
source file
#include "stdafx.h"
#include "xRegistry.h"
#include <string>
#include <windows.h>
#include <winreg.h> //using windows.h
#pragma warning (disable: 4996)

Registry::Registry(const TCHAR* lpDefKeyName/*Software/leizi*/, void* hDefRootKey/*HKEY_CURRENT_USER*/)
{
    m_hKeyOpened = NULL;
    SetRootKey(hDefRootKey);
    OpenKey(lpDefKeyName,true);
}

Registry::~Registry()
{
    if (m_hKeyOpened != NULL) {
        RegCloseKey((HKEY)m_hKeyOpened);
        m_hKeyOpened = NULL;
    }
}

bool Registry::SetRootKey(void* hRootKey/*HKEY_CURRENT_USER*/)
{
    if (hRootKey != HKEY_CLASSES_ROOT &&
        hRootKey != HKEY_CURRENT_USER &&
        hRootKey != HKEY_LOCAL_MACHINE &&
        hRootKey != HKEY_USERS)
        return false;
    m_hRootKey = hRootKey;
    return true;
}

int trimleft(TCHAR* s)
{
    if (!s) return -1;
    TCHAR* p = s;
    while (*p && ((_T(' ') == *p) || (_T('\t') == *p) || (_T('\\') == *p))) p++;
    if (*p) _tcscpy(s, p);
    else *s = 0;
    return 0;
}
int trimright(TCHAR* s)
{
    if (!s) return -1;
    TCHAR* p = s + _tcslen(s) - 1;
    while (*p && (p - s) && ((_T(' ') == *p) || (_T('\t') == *p) || (_T('\\') == *p))) p --;
    *(p + 1) = 0;
    if ((_T(' ') == *p) || (_T('\t') == *p) || (_T('\\') == *p)) *p = 0;
    return 0;
}
// if the subkey already exist,this function just like RegOpenKeyEx().
// if the subkey does not exist,we will call RegCreateKey() recursively
bool Registry::OpenKey(const TCHAR* lpRegKey,bool bCreateIfNoExist/*=TRUE*/)
{
    if (!lpRegKey) return false;
    if (m_hKeyOpened != NULL) {
        RegCloseKey((HKEY)m_hKeyOpened);
        m_hKeyOpened = NULL;
    }

    // here,save the opened key handle
    if (ERROR_SUCCESS == RegOpenKeyEx((HKEY)m_hRootKey,lpRegKey,0,KEY_ALL_ACCESS, (HKEY*)&m_hKeyOpened)) {
        _tcscpy(m_szOpenedKey,lpRegKey);
        return true;
    } else { // this subkey does'nt exist in registry
        if (bCreateIfNoExist) {
            TCHAR szPath[MAX_PATH];
            _tcscpy(szPath,lpRegKey);
            trimright(szPath);

#ifdef UNICODE
            std::wstring sReg(szPath);
            sReg.append(_T("\\"));
            std::wstring sTmp;
#else
            std::string sReg(szPath);
            sReg.append(_T("\\"));
            std::string sTmp;
#endif
            int nFind = 0;
            while (1) {
                nFind = sReg.find(_T('\\'),nFind);
                if (nFind < 0) break;
                if (m_hKeyOpened) RegCloseKey((HKEY)m_hKeyOpened);

                sTmp = sReg.substr(0,nFind);
                if (ERROR_SUCCESS == RegOpenKey((HKEY)m_hRootKey,sTmp.c_str(), (HKEY*)&m_hKeyOpened)) {
                    RegCloseKey((HKEY)m_hKeyOpened);
                    m_hKeyOpened = NULL;
                } else {
                    RegCreateKey((HKEY)m_hRootKey,sTmp.c_str(),(HKEY*)&m_hKeyOpened);
                }
                nFind++;
            }
        }

        if (m_hKeyOpened != NULL)
            return true;
    }
    m_hRootKey = HKEY_CURRENT_USER;
    m_hKeyOpened = NULL;
    return false;
}

void Registry::GetKey(TCHAR* lpszRegKey, void**phRootKey)
{
    if (!lpszRegKey || !phRootKey) return;
    *phRootKey = m_hRootKey;
    _tcscpy(lpszRegKey,m_szOpenedKey);
}

// if the value(wait be setted) is a string,the third param is 0 & last param is ignored
bool Registry::SetValue(const TCHAR* lpItem,void* pValue,unsigned long dwLen/*sizeof(DWORD)*/,unsigned long dwType/*=REG_DWORD*/)
{
    unsigned long dwSetType = dwType;
    unsigned long dwSetSize = dwLen;
    if (dwLen == 0) {
        dwSetType = REG_SZ;
        dwSetSize = _tcslen((TCHAR*)pValue);
    }
    if (m_hKeyOpened==NULL || pValue==NULL ||
        ERROR_SUCCESS!=RegSetValueEx((HKEY)m_hKeyOpened,lpItem,0,dwSetType,(CONST BYTE *)pValue,dwSetSize))
        return false;

    return true;
}

bool Registry::GetValue(const TCHAR* lpItem,void *pValue,unsigned long *pdwLen/*=NULL*/,unsigned long *pdwType/*NULL*/)
{
    if (m_hKeyOpened==NULL || pValue==NULL)
        return false;

    unsigned long dwLen=0,dwType=0;
    // first check the item to see if it exist. if it does exist,get the value, type and length
    bool bGetOK = (ERROR_SUCCESS == RegQueryValueEx((HKEY)m_hKeyOpened,lpItem,NULL,&dwType,NULL,&dwLen) &&
                      ERROR_SUCCESS == RegQueryValueEx((HKEY)m_hKeyOpened,lpItem,NULL,&dwType,(BYTE*)pValue,&dwLen));

    if (pdwType != NULL)
        *pdwType = dwType;

    if (pdwLen != NULL)
        *pdwLen = dwLen;

    if (dwType == REG_SZ)
        ((TCHAR *)pValue)[dwLen] = 0;

    return bGetOK;
}

void Registry::FreeRegItem(void *pItem)
{
    if (pItem != NULL) {
        if (((RegItem*)pItem)->pValueBuf != NULL)
            free(((RegItem*)pItem)->pValueBuf);
        free(pItem);
        pItem = NULL;
    }
}

bool Registry::DelValue(const TCHAR* lpItem)
{
    if (m_hKeyOpened==NULL || ERROR_SUCCESS!=RegDeleteValue((HKEY)m_hKeyOpened,lpItem))
        return false;
    return true;
}

#ifdef __AFXWIN_H__
// you are be responsable for freeing the mem which is associate with the first arg
bool Registry::EnumKeyValues(CArray<RegItem*,RegItem*> &arrValues,const TCHAR* lpRegKey/*NULL*/)
{
    if (!lpRegKey)
        return false;

    // 先保存之前打开的键
    TCHAR szOldKeyName[1024] = {0};
    _tcscpy(szOldKeyName,m_szOpenedKey);
    arrValues.RemoveAll();

    // 会改变 m_sOpenedKey
    if (!OpenKey(lpRegKey,false))
        return false;

    TCHAR szItemName[256]  ={0};
    BYTE szItemValue[4096] ={0};
    for (unsigned long i=0; ; i++)
    {
        unsigned long dwType = 0;
        unsigned long dwNameLen   = sizeof(szItemName);
        unsigned long dwValueLen  = sizeof(szItemValue);
        memset(szItemName ,0,sizeof(szItemName));
        memset(szItemValue,0,sizeof(szItemValue));

        if (ERROR_NO_MORE_ITEMS == RegEnumValue((HKEY)m_hKeyOpened,i,szItemName,&dwNameLen,0,&dwType,szItemValue,&dwValueLen))
            break;

        RegItem* lpItem = (RegItem*)calloc(1,sizeof(RegItem));
        _tcscpy(lpItem->szItemName,szItemName);
        lpItem->pValueBuf = (BYTE *)calloc(dwValueLen+1,sizeof(BYTE));
        memcpy(lpItem->pValueBuf,szItemValue,dwValueLen);

        arrValues.Add(lpItem);
    }

    OpenKey(szOldKeyName,false); // 恢复之间打开的key
    return true;
}
#endif

bool Registry::EnumKeyValues( std::vector<RegItem*>& arrValues,const TCHAR* lpRegKey/*=NULL*/)
{
    if (!lpRegKey) return false;

    TCHAR szOldKeyName[1024] = {0};
    _tcscpy(szOldKeyName,m_szOpenedKey);
    arrValues.clear();

    if (!OpenKey(lpRegKey,false))
        return false;

    TCHAR szItemName[256]  ={0};
    BYTE szItemValue[4096] ={0};
    for (unsigned long i=0; ; i++)
    {
        unsigned long dwType = 0;
        unsigned long dwNameLen   = sizeof(szItemName);
        unsigned long dwValueLen  = sizeof(szItemValue);
        memset(szItemName ,0,sizeof(szItemName));
        memset(szItemValue,0,sizeof(szItemValue));

        if (ERROR_NO_MORE_ITEMS == RegEnumValue((HKEY)m_hKeyOpened,i,szItemName,&dwNameLen,0,&dwType,szItemValue,&dwValueLen))
            break;

        RegItem* lpItem = (RegItem*)calloc(1,sizeof(RegItem));
        _tcscpy(lpItem->szItemName,szItemName);
        lpItem->pValueBuf = (BYTE *)calloc(dwValueLen+1,sizeof(BYTE));
        memcpy(lpItem->pValueBuf,szItemValue,dwValueLen);

        arrValues.push_back(lpItem);
    }

    OpenKey(szOldKeyName,false); // rollback
    return true;
}

#ifdef __AFXWIN_H__
bool Registry::EnumSubkeys(CStringArray &arrSubkeys,const TCHAR* lpRegKey/*NULL*/)
{
    if (!lpRegKey) return false;
    if (!OpenKey(lpRegKey,false)) return false;

    TCHAR szKeyName[1024] = {0};
    arrSubkeys.RemoveAll();
    for (unsigned long i=0; ; i++) {
        if (ERROR_NO_MORE_ITEMS == RegEnumKey((HKEY)m_hKeyOpened,i,szKeyName,1024))
            break;
        arrSubkeys.Add(szKeyName);
    }

    OpenKey(m_szOpenedKey,false);
    return true;
}
#endif

#ifdef UNICODE
bool  Registry::EnumSubkeys(std::vector<std::wstring>& arrSubkeys,const TCHAR* lpRegKey/*=NULL*/)
#else
bool  Registry::EnumSubkeys(std::vector<std::string>& arrSubkeys,const TCHAR* lpRegKey/*=NULL*/)
#endif
{
    if (!lpRegKey) return false;

    // 打开注册表
    if (!OpenKey(lpRegKey,false)) return false;

    TCHAR szKeyName[1024] = {0};
    arrSubkeys.clear();
    for (unsigned long i=0; ; i++) {
        if (ERROR_NO_MORE_ITEMS == RegEnumKey((HKEY)m_hKeyOpened,i,szKeyName,1024))
            break;
        arrSubkeys.push_back(szKeyName);
    }

    OpenKey(m_szOpenedKey,false);
    return true;
}

void Registry::SetAutoRunOnBoot(TCHAR *pStartName,bool bEnable,TCHAR *pExeFullPath/*=NULL*/)
{
    HKEY hKey;
    RegOpenKey(HKEY_CURRENT_USER, _T("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run"), &hKey);
    if (!bEnable) {
        RegDeleteValue(hKey, pStartName);
        RegCloseKey(hKey);
        return;
    }
#ifdef UNICODE
    std::wstring sRunPath(pExeFullPath);
#else
    std::string sRunPath(pExeFullPath);
#endif
    TCHAR szAppPathName[MAX_PATH];
    GetModuleFileName(NULL,szAppPathName,MAX_PATH);

    if (sRunPath.empty()) sRunPath = szAppPathName;
    sRunPath.append(_T(" /OnSysStart"));
    const BYTE *pData = (BYTE *)sRunPath.c_str();
    RegSetValueEx(hKey, pStartName, 0, REG_SZ, pData, sRunPath.length());
    RegCloseKey(hKey);
}